I want to print hello world
const obs = new Observable( (observer)=>{ setTimeout(observer.next, 0) } );
obs.subscribe(()=>{console.log("world")});
console.log("hello ");
This gives an error this._next is not a function
If I instead write the following it works fine:
const obs = new Observable( (observer)=>{ setTimeout(()=>{observer.next()}, 0) } );
obs.subscribe(()=>{console.log("world")});
console.log("hello ");
Why can't I pass the reference to observer.next callback directly to setTimeout()?
In RXJS the internals of the .next()
function use this
. To get a better understanding, the next
method is defined like so:
next(value: T): void {
if (this.isStopped) {
handleStoppedNotification(nextNotification(value), this);
} else {
this._next(value!);
}
}
The value of this
inside of this method depends on how it is called (see this for more info). When you call it using:
observer.next()
as you do in your second example, the this
value gets set to the observer
object you called the next
method on, allowing it to function correctly when the internals eventually end up calling ._next()
on the observer
object. However, when you pass the next
function reference to setTimeout()
in your first example:
setTimeout(observer.next, 0)
you lose the this
context (that being the observer
), as now you're just passing the function reference of next
to setTimeout()
, and not calling the method on a particular object anymore. When setTimeout()
eventually invokes the next
function after the specified delay, it doesn't have any information about where the function it's calling came from, and so the this
value inside of the next
method once its invoked defaults to the global object, or undefined in strict mode, which both don't have _next()
methods.
An alternative would be to .bind()
the observable to the function, which returns a new function with the this
value set explicitly to the observable
:
setTimeout(observer.next.bind(observer), 0)