【问题标题】:RxJS - observable doesn't complete when an error occursRxJS - 发生错误时观察到的不会完成
【发布时间】:2016-02-20 10:04:00
【问题描述】:

当我从头开始创建一个可观察对象,并出现观察者错误,然后完成时,订阅的完成部分永远不会被调用。

var observer = Rx.Observable.create(function(observer){
    observer.onError(new Error('no!'));
    observer.onCompleted();
})

observer.subscribe(
    function(x) { console.log('succeeded with ' + x ) },
    function(x) { console.log('errored with ' + x ) },
    function() { console.log('completed') }
)

输出是:

errored with Error: no!

我希望它是:

errored with Error: no!
completed

如果我将代码更改为调用 onNext 而不是 onError,则 observable 会正确完成:

var observer = Rx.Observable.create(function(observer){
    observer.onNext('Hi!');
    observer.onCompleted();
})

observer.subscribe(
    function(x) { console.log('succeeded with ' + x ) },
    function(x) { console.log('errored with ' + x ) },
    function() { console.log('completed') }
)

我得到了预期的输出:

succeeded with Hi! 
completed

发生错误时为什么不完成?

【问题讨论】:

    标签: javascript angular rxjs reactive-programming


    【解决方案1】:

    另一个可能也是最简单的解决方案可能是使用add() 函数。
    无论出现错误,该语句都将始终执行 发生与否(如大多数编程语言中的finally 语句)。

    observer.subscribe(
        function(x) { console.log('succeeded with ' + x ) },
        function(x) { console.log('errored with ' + x ) },
        function() { console.log('completed') }
    )
    .add(() => {
        console.log("Will be executed on both success or error of the previous subscription")
    );
    

    【讨论】:

    • 就像一个魅力,当 finally() 不起作用时出现错误
    【解决方案2】:

    要在 observable 完成或错误时运行回调,您应该使用 finalize。

    例如:

    this.service.yourObservable
                .pipe(
                   finalize(() => {
                     // * This will always run when observable finishes the stream
                     console.log("Finally!");
                     // * callback for finally
                    })  
                 ).subscribe(
                  {
                   next: () => { // * Callback for success },
                   error: () => { // * Callback for error },
                   complete: () => {// * This gets called only on success }
                  })
    

    【讨论】:

      【解决方案3】:

      这是因为错误意味着完成,所以与onCompleted 关联的回调永远不会被调用。你可以在这里查看 Rxjs 的 observables 合约 (http://reactivex.io/documentation/contract.html):

      一个 Observable 可以发出零个或多个 OnNext 通知,每个通知代表一个发射的项目,然后它可以通过 OnCompleted 或 OnError 通知跟随这些发射通知,但不能两者兼而有之。在发出 OnCompleted 或 OnError 通知后,它可能不会再发出任何进一步的通知。`

      对于错误管理,您可以查看: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/errors.md

      【讨论】:

        【解决方案4】:

        当我有同样的问题时,我碰到了这个github issue

        显然在这种情况下需要使用Observable对象的finally方法。

        从该线程中引用 Aleksandr-Leotech:

        完成和最终是完全不同的事情。完整的意思是 可观察到的蒸汽已成功完成。因为你可以拥有 许多成功的电话。 finally 意味着蒸汽已经结束,要么 成功与否。

        HTTP 请求并不明显,但想象一下另外两个 场景。

        1. 鼠标事件。您将获得永无止境的成功 回调,但你永远不会收到 finally 或 complete,因为 用户事件永远不会停止(除非您触发异常 错误的代码,然后你会得到错误,最后)。

        2. 使用网络套接字。您将收到多个成功回调,但在某个时间点,您与后端的通信将停止,您将获得 complete 和 finally,除非您有一些错误,这将调用 error 和 finally。

        因此,您可能会收到多次或没有成功调用、零次或一次错误调用、零次或一次完成以及最终是零次或一次。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-17
          • 1970-01-01
          • 2021-12-20
          • 2020-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多