RxJS - 发生错误时可观察对象未完成

RxJS - observable doesn't complete when an error occurs

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

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,则可观察对象会正确完成:

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

为什么出现错误却没有完成?

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

An Observable may make zero or more OnNext notifications, each representing a single emitted item, and it may then follow those emission notifications by either an OnCompleted or an OnError notification, but not both. Upon issuing an OnCompleted or OnError notification, it may not thereafter issue any further notifications.`

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

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

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

从该线程中引用 Aleksandr-Leotech 的话:

Complete and finally are totally different things. Complete means that the observable steam was finished successfully. Because you can have many success calls. Finally means that steam has ended, either successfully or not.

It is not obvious with HTTP requests, but imagine two additional scenarios.

  1. Mouse events. You will be receiving a never-ending steam of success callbacks, but you will never receive finally or complete, because user events will never stop (unless you trigger an exception with buggy code, then you will get error and finally).

  2. Working with web sockets. You will get multiple success callbacks, but at some point in time your communication with back end will stop and you will get both complete and finally unless you have some errors, which will call error and finally.

So, you might be getting multiple or no success calls, zero or one error call, zero or one complete and zero or one finally.

另一个可能是最简单的解决方案可能是使用 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")
);

为了 运行 当 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 }
              })