当我从头开始创建一个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') }
)
输出结果为:
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
发生错误时为什么没有完成?
答案 0 :(得分:39)
这是因为错误意味着完成,因此与onCompleted
相关联的回调永远不会被调用。您可以在此处查看可观察量的Rxjs合约(http://reactivex.io/documentation/contract.html):
Observable可以制作零个或多个OnNext通知,每个通知代表一个发出的项目,然后它可以通过OnCompleted或OnError通知跟踪这些发射通知,但不能同时通过两者。在发出OnCompleted或OnError通知后,它可能不会再发出任何通知。
对于错误管理,您可以查看: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/errors.md
答案 1 :(得分:14)
当我遇到同样的问题时,我碰到了github issue。
在这种情况下,显然需要使用finally
Observable
对象的方法。
从该线程引用Aleksandr-Leotech:
完成并最终是完全不同的事情。完成意味着 可观察到的蒸汽成功完成。因为你可以拥有 许多成功电话。最后意味着蒸汽已经结束 成功与否。
HTTP请求并不明显,但想象另外两个 场景。
鼠标事件。你将获得永无止境的成功 回调,但你永远不会收到或完成,因为 用户事件永远不会停止(除非您触发异常) 有缺陷的代码,然后你会得到错误,最后)。
- 醇>
使用网络套接字。您将获得多次成功回调,但在某个时间点,您与后端的通信将停止,您将获得完整和最终,除非您有一些错误,这将最终调用错误。
所以,你可能会得到多次或没有成功的调用,零或一次错误调用,零或一个完整,零或一个最终。
答案 2 :(得分:5)
另一个可能也是最简单的解决方案可能是使用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")
);
答案 3 :(得分: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 }
})