Javascript RxJS-可观测的不可观测数据';发生错误时,无法完成

Javascript RxJS-可观测的不可观测数据';发生错误时,无法完成,javascript,angular,rxjs,reactive-programming,Javascript,Angular,Rxjs,Reactive Programming,当我从头开始创建一个可观察对象,并出现观察者错误,然后完成时,订阅的完成部分将永远不会被调用 var observer = Rx.Observable.create(function(observer){ observer.onError(new Error('no!')); observer.onCompleted(); }) observer.subscribe( function(x) { console.log('succeeded with ' + x ) }

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

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合同中的可观测项():

一个可观测对象可以发出零个或多个OnNext通知,每个通知表示一个已发射的项目,然后它可以在这些发射通知之后发出一个未完成或一个错误通知,但不能同时发出这两个通知。发出未完成或错误通知后,不得再发出任何通知`

对于错误管理,您可以查看:
当我有同样的问题时,我碰到了这个问题

显然,
最后
在这种情况下需要使用
可观察
对象的方法

引用Aleksandr Leotech的话:

完全和最终是完全不同的事情。完全意味着 可观察到的蒸汽成功地完成了。因为你可以 许多成功的呼唤。最后意味着蒸汽也已经结束了 成功与否

这在HTTP请求中并不明显,但可以想象另外两种情况 情景

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

  • 使用web套接字。您将获得多个成功回调,但在某个时间点,您与后端的通信将停止,并且您将获得完整和最终的回调,除非您有一些错误,这将调用error和finally

  • 因此,您可能会收到多个或没有成功调用,零个或一个错误调用,零个或一个完整调用,零个或一个最终调用


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


    要在observable完成或出现错误时运行回调,应使用finalize

    例:

    就像一个符咒,当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")
    );
    
    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 }
                  })