发生错误时,rxjs observable无法完成

Ove*_*d D 44 javascript reactive-programming rxjs angular

当我从头创建一个observable并且有观察者错误然后完成时,永远不会调用订阅的完成部分.

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') }
)
Run Code Online (Sandbox Code Playgroud)

输出是:

errored with Error: no!
Run Code Online (Sandbox Code Playgroud)

我希望它是:

errored with Error: no!
completed
Run Code Online (Sandbox Code Playgroud)

如果我更改代码以调用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') }
)
Run Code Online (Sandbox Code Playgroud)

我得到了预期的输出:

succeeded with Hi! 
completed
Run Code Online (Sandbox Code Playgroud)

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

use*_*222 48

那是因为错误意味着完成,因此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


ezh*_*a99 26

要在 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 }
              })
Run Code Online (Sandbox Code Playgroud)

  • 如果“完整”只在成功时才触发,那它还有什么意义呢? (4认同)
  • @RichardBarraclough“next”可以被触发多次并携带数据,“complete”明确告诉您,不会再触发任何内容(并且没有数据),“error”意味着出现了问题,并提供了有关出现问题的信息。没有自动恢复,错误意味着我死了,这就是原因,由您决定是否使用重试运算符。 (2认同)

con*_*i2k 15

当我遇到同样的问题时,我碰到了这个github问题.

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

从该线程引用Aleksandr-Leotech:

完成,最后是完全不同的事情.完成意味着可观察的蒸汽成功完成.因为你可以有很多成功的电话.最后意味着蒸汽已成功或未成功结束.

HTTP请求并不明显,但想象另外两种情况.

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

  2. 使用Web套接字.您将获得多次成功回调,但在某个时间点,您与后端的通信将停止,您将获得完整和最终,除非您有一些错误,这将调用错误,最后.

因此,您可能会获得多次或没有成功调用,零或一次错误调用,零或一个完整,零或一个最终.


Jus*_*dow 5

Another and probably the simplest solution might be using add() function.
In this case the statement will be always executed regardless error occured or call succeded (alike finally in most programming languages).

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")
);
Run Code Online (Sandbox Code Playgroud)

  • 就像一个魅力,当finally() 不起作用并出现错误时 (3认同)