In short:
How to proceed listening after an error in stream without putting a .catch
before every .subscribe
?
If you need more details they are here:
Lets assume I have a Subject of current user or null. I get the data from API sometimes and send to the Subject. It updates the view accordingly. But at some point error occurs on my server and I want my application to continue working as before but notify some places about the error and KEEP listening to my Subject.
Initially I thought that if I just do userSubject.error(...)
it will only trigger .catch
callback and error
handlers on subscribes and skip all success handlers and chains.
And if after I call userSubject.next(...)
all my chains and subscribers will work as before
BUT unluckily it is not the case. After the first uncaught .error
it unsubscribes subscribers from the stream and they do not operate any more.
So my question: Why???
And what to do instead if I want to handle null
value normally but also handle errors only in some places?
Here is the link to RxJs source code where Subscriber unsubscribes on error https://github.com/ReactiveX/rxjs/blob/master/src/Subscriber.ts#L140
Rx
observables follow the grammar next*(error|complete)?
, meaning that they can produce nothing after error
or complete
notification has been delivered.
An explanation of why this matters can be found from Rx design guidelines:
The single message indicating that an observable sequence has finished ensures that consumers of the observable sequence can deterministically establish that it is safe to perform cleanup operations.
A single failure further ensures that abort semantics can be maintained for operators that work on multiple observable sequences.
In short, if you want your observers to keep listening to the subject after a server error has occurred, do not deliver that error to the subject, but rather handle it in some other way (e.g. use catch
, retry
or deliver the error to a dedicated subject).
Every Observable emits zero or more next
notifications and one error
or complete
but never both.
For this reason, Subjects have internal state.
Then it depends how you construct your chain. For example you can use retry()
to resubscribe to its source Observable on error.
Or when you pass values to your Subject you can send only next
notifications and ignore the other two:
.subscribe(v => subject.next(v));
Or if you want to throw error when the user is null
you can use any operator that captures exceptions and sends them as error notifications. For example like this:
.map(v => {
if (v === null) {
throw new Error("It's broken");
}
return v;
})
Anyway it's hard to give more precise advice without any code.
来源:https://stackoverflow.com/questions/45476902/why-does-rxjs-unsubscribe-on-error