当发生错误时,RxJS- 可观察的不完成

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

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

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

44812 次浏览

这是因为错误意味着完成,所以从未调用与 onCompleted相关联的回调。你可以在这里查看 Rxjs 的可观测合同(http://reactivex.io/documentation/contract.html) :

可观察对象可以发出零个或多个 OnNext 通知,每个通知代表一个发出的项目,然后它可以通过 OnCompleted 或 OnError 通知跟踪这些发出通知,但不能同时跟踪这两个通知。在发出 OnCompleted 或 OnError 通知后,它可能不会随后发出任何进一步的通知。`

对于错误管理,您可以看一下: Https://github.com/reactive-extensions/rxjs/blob/master/doc/gettingstarted/errors.md

正当我有同样的问题时,我碰到了这个 Github 的问题

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

引用 Aleksandr-Leotech 的话:

完整和最终是完全不同的东西。完整意味着 可观察到的蒸汽已经成功地完成了。因为你可以 许多成功的呼吁。最终意味着蒸汽已经结束,要么 不管成功与否。

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

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

  2. 使用 Web 套接字。您将获得多个成功回调,但是在某个时间点,您与后端的通信将停止,您将同时获得完整和最终的回调,除非您有一些错误,这些错误将调用 error 和 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")
);

若要在可观察到的完成或错误时运行回调,应使用 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 }
})