RxJS - 发生错误时观察到的不会完成
Posted
技术标签:
【中文标题】RxJS - 发生错误时观察到的不会完成【英文标题】:RxJS - observable doesn't complete when an error occurs 【发布时间】: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
发生错误时为什么不完成?
【问题讨论】:
【参考方案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 请求并不明显,但想象一下另外两个 场景。
鼠标事件。您将获得永无止境的成功 回调,但你永远不会收到 finally 或 complete,因为 用户事件永远不会停止(除非您触发异常 错误的代码,然后你会得到错误,最后)。
使用网络套接字。您将收到多个成功回调,但在某个时间点,您与后端的通信将停止,您将获得 complete 和 finally,除非您有一些错误,这将调用 error 和 finally。
因此,您可能会收到多次或没有成功调用、零次或一次错误调用、零次或一次完成以及最终是零次或一次。
【讨论】:
以上是关于RxJS - 发生错误时观察到的不会完成的主要内容,如果未能解决你的问题,请参考以下文章