1

In RxJS version 5, the following code results in the process being terminated after three iterations of both subscriptions:

var Rx = require("rxjs");

const published$ = Rx.Observable.interval(1000).publish();

published$.subscribe(index => {
    console.log(`One: ${index}`);

    if (index == 3) throw new Error("ded.");
});

published$.forEach(index => {
    console.log(`Two: ${index}`);
});

published$.connect();

However, my understanding was that an error thrown in the next handler would simply unsubscribe that particular subscription, and not cause the underlying observable to terminate. My expected output would be that the "One" subscription would unsubscribe, but the interval would continue to produce results to the "Two" subscription.

This behavior is causing me issues, where I may have multiple subscriptions to an underlying hot observable - yet a single exception thrown on any of those subscriptions causes the underlying observable to completely terminate.

It's especially annoying when I'm in development using hot module reloading, since any programming error in any subscription causes me to have to refresh the entire page to re-start the observable sequences.

Is there a way, without wrapping each of my subscriptions in a try/catch, to have an exception thrown in my next handler to simply unsubscribe that ONE subscription, and not terminate the underlying observable?

------------ EDIT ------------

I've found the behavior that I'm looking for, by setting syncErrorThrowable to true on the subscription object returned by "subscribe". It seems that the only time this is ever set to true in the codebase is via the "do" operator.

Should I take advantage of this field? I feel pretty dirty using it, but on the other hand I find it strange that the "do" operator has different error handling semantics than the "next" subscription handler.

Here's the primary block of code affected by this flag: https://github.com/ReactiveX/RxJS/blob/master/src%2FSubscriber.ts#L132

If it's set to false, this method gets invoked: https://github.com/ReactiveX/RxJS/blob/master/src%2FSubscriber.ts#L179

Whereas if it's set to true, this method is used instead: https://github.com/ReactiveX/RxJS/blob/master/src%2FSubscriber.ts#L188

The difference is that the first method will re-throw the exception back up the callstack, whereas the second one instead propagates the error forward to subsequent subscriptions.

Why does the do operator propagate the error forward, whereas the "next" handler bubbles the error back up? This seems odd to me.

4

1 回答 1

0

不,不要使用该字段。如果您将其改回 true,您的订阅将开始吞下错误。

这是我们用来知道订阅是同步通知(在与源 Observable 的订阅调用相同的块中)还是异步通知的一些私有状态。如果在同步通知期间从订阅者的消息处理程序之一抛出错误,我们会推迟重新抛出它,直到我们退出 Observable 的订阅回调。 [1]

如果您的处理程序抛出您希望转发给订阅onError处理程序的错误,目前的指导是将它们移动到do订阅上方的块中。

不,我不同意这种行为。以下是一些上下文链接:

[1] 来源:我写了这段代码。

于 2016-03-03T03:37:32.023 回答