Reputation: 1334
I have this example code sequence that I either run in Angular or in a node app. Behavior is different, and I would like to know why.
of(1, 2, 3, 4).subscribe((x) => {
console.log(`x: ${x}`);
if (x === 2) {
throw new Error('xxx');
}
});
When executing in node all four numbers are written to the console. Exception is shown afterwards.
When executing in Angular, e.g. in any ngOnInit(), it only logs 1 and 2 and then the Observable is terminated. The consequence is that any exception in a subscription block breaks the program.
Is there any description of why and how this difference in behavior.
Addendum: Reading more on the subject, the Angular (or more general the browser) behavior is what is to be expected. It is really the node.js behavior that is surprising. Why does the node.js program not stop after two digits?
Upvotes: 0
Views: 392
Reputation: 1685
From the comments section, you are actually trying to figure out the difference in behavior between the rxjs v6 and v7
in terms of handling the consumer thrown
unhandled errors.
In general throwing errors from the observers is a bad idea as it will lead to blocking of the observables if shared between multiple
observers. This problem is handled in the v6
by improving the error handling mechanism as mentioned here SafeSubscriber
and more specifically in next
. Below snapshot of the next
next(value?: T): void {
if (!this.isStopped && this._next) {
const { _parentSubscriber } = this;
if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
this.__tryOrUnsub(this._next, value);
} else if (this.__tryOrSetError(_parentSubscriber, this._next, value)) {
this.unsubscribe();
}
}
}
If you see from the above snapshot when an unhandled error is thrown from the observer the code is trying to subscribe
and then if error it is unsubscribing
the observable in __tryOrUnsub
. Finally the error is added to call stack and thrown once the call stack is empty from method hostReportError
(once all the observers complete asynchronously
). Below is the sample stackblitz to demonstrate the same.
https://stackblitz.com/edit/angular-ivy-v7dojh?file=src%2Fapp%2Fhello.component.ts
This logic further changed in v7
as mentioned by the this commit
. The unsubscribing logic is removed and the asynchronous
error call stack is maintained as shown below sample stackblitz, due to which the all the 4 elements are printed and the error is printed to console once the call stack is empty asynchronously usning reportUnhandledError
-
https://stackblitz.com/edit/angular-ivy-p8zj2k?file=src%2Fapp%2Fhello.component.ts
Upvotes: 2