RxJS - 在onNext发生错误后继续发送通知

时间:2017-01-05 18:37:06

标签: rxjs reactive-programming reactive-extensions-js

我是Rx的新手,我非常感谢错误处理方面的一些帮助。我有以下代码,基本上是一个类型:

var observable = Rx.Observable.fromEvent(searchField, 'keyup')
    .map(ev => ev.target.value)
    .filter(text => text.length > 2)
    .debounce(500 /* ms */)
    .distinctUntilChanged()
    .flatMapLatest(getAsyncSearchResults);

observable.subscribe(function(value) {
        console.log("onNext");
        throw "error"; // THIS TERMINATES THE OBSERVABLE
    },
    function(error) {
        console.log("Error");
    },
    function() {
        console.log("Completed");
    });

在onNext函数发生异常后,Observable终止。这对我来说似乎是一个不受欢迎的行为,因为我不想将所有的onNext代码包装在try-catch中。有什么方法可以告诉观察者不管发生什么异常都会发出通知吗?

3 个答案:

答案 0 :(得分:2)

您应该确保nextcompletederror处理程序对例外安全。源流没有合理的方式来恢复"订阅者错误时的订阅 - 唯一合理的做法是停止与订阅者交谈。

有关为什么会看到我的答案How to handle exceptions thrown by observer's onNext in RxJava?的完整讨论 - 这同样适用于Rx的任何平台实现。

此外,请参阅Why is the OnError callback never called when throwing from the given subscriber?以获得考虑因素的良好解释性比喻(新闻报道) - 尤其需要考虑可能其他订阅者未在其{{ {1}}处理程序。

答案 1 :(得分:2)

您需要切换到新的一次性流,如果在其中发生错误,将安全地处理,并保持原始流的活动。

我已将您的代码修改为更简单的0 - 5流,以便轻松演示。如果数字为3,则抛出错误/异常。

Rx.Observable.from([0,1,2,3,4,5])
    .switchMap(value => {

        // This is the disposable stream!
        // Errors can safely occur in here without killing the original stream

        return Rx.Observable.of(value)
            .map(value => {
                if (value === 3) {
                    throw new Error('Value cannot be 3');
                }
                return value;
            })
            .catch(error => {
                // You can do some fancy stuff here with errors if you like
                // Below we are just returning the error object to the outer stream
                return Rx.Observable.of(error);
            });

    })
    .map(value => {
        if (value instanceof Error) {
            // Maybe do some error handling here
            return `Error: ${value.message}`;
        }
        return value;
    })
    .subscribe(
      (x => console.log('Success', x)),
      (x => console.log('Error', x)),
      (() => console.log('Complete'))
    );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>

此博客文章中有关此技术的更多信息:The Quest for Meatballs: Continue RxJS Streams When Errors Occur

答案 2 :(得分:0)

这就是Rx在每个平台上的行为,而在观察者中捕获异常的唯一方法就是......好吧......抓住它们。

您可以创建自己的subscribeSafe方法,如果您经常需要,可以在try / catch中包装回调。

或者,如果您可以将从观察者投掷的部分移动到流本身,则可以控制错误流,并(例如)重试。

以下示例:

&#13;
&#13;
// simulates (hot) keyup event
const obs1 = Rx.Observable.interval(1000).publish()
obs1.connect()

function getAsyncSearchResults(i) {
  return Rx.Observable.timer(500).mapTo(i)
}

obs1.switchMap(getAsyncSearchResults).do(x => {
  console.log(x) // all events gets logged
  throw new Error()
}).retry().subscribe()
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.2/Rx.js"></script>
&#13;
&#13;
&#13;