在订阅上最终可观察到
Posted
技术标签:
【中文标题】在订阅上最终可观察到【英文标题】:Observable Finally on Subscribe 【发布时间】:2017-04-04 02:14:01 【问题描述】:根据this artcle,onComplete
和onError
函数subscribe
是互斥的。
意味着onError
或onComplete
事件将在我的subscribe
中触发。
我有一个逻辑块,无论我收到错误还是成功完成信息流,都需要执行该逻辑块。
我查找了类似finally
in python 的东西,但我发现的只是finally
,它需要附加到我创建的可观察对象上。
但我只想在订阅时执行该逻辑,并且在流结束后,无论是成功还是出错。
有什么想法吗?
【问题讨论】:
【参考方案1】:我现在在 Angular 应用程序中使用 RxJS 5.5.7 并且使用 finalize
运算符对我的用例有一个奇怪的行为,因为在成功或错误回调之前被触发。
简单示例:
// Simulate an AJAX callback...
of(null)
.pipe(
delay(2000),
finalize(() =>
// Do some work after complete...
console.log('Finalize method executed before "Data available" (or error thrown)');
)
)
.subscribe(
response =>
console.log('Data available.');
,
err =>
console.error(err);
);
我不得不在订阅中使用add
方法来完成我想要的。基本上是在成功或错误回调完成后的finally
回调。像 try..catch..finally
块或 Promise.finally
方法。
简单示例:
// Simulate an AJAX callback...
of(null)
.pipe(
delay(2000)
)
.subscribe(
response =>
console.log('Data available.');
,
err =>
console.error(err);
)
.add(() =>
// Do some work after complete...
console.log('At this point the success or error callbacks has been completed.');
);
【讨论】:
自发布此答案以来,finalize 运算符必须已更改。使用您发布的说明 finalize 运算符被过早调用的代码,它按预期工作。【参考方案2】:此运算符的当前“pipable”变体称为finalize()
(从 RxJS 6 开始)。较旧且现已弃用的“补丁”运算符称为 finally()
(直到 RxJS 5.5)。
我认为finalize()
运算符实际上是正确的。你说:
仅在我订阅时以及流结束后执行该逻辑
我认为这不是问题。如果需要,您可以拥有一个 source
并在订阅之前使用 finalize()
。这样你就不需要总是使用finalize()
:
let source = new Observable(observer =>
observer.next(1);
observer.error('error message');
observer.next(3);
observer.complete();
).pipe(
publish(),
);
source.pipe(
finalize(() => console.log('Finally callback')),
).subscribe(
value => console.log('#1 Next:', value),
error => console.log('#1 Error:', error),
() => console.log('#1 Complete')
);
source.subscribe(
value => console.log('#2 Next:', value),
error => console.log('#2 Error:', error),
() => console.log('#2 Complete')
);
source.connect();
这会打印到控制台:
#1 Next: 1
#2 Next: 1
#1 Error: error message
Finally callback
#2 Error: error message
2019 年 1 月:针对 RxJS 6 更新
【讨论】:
有趣的是,这是一种与 Promise 完全相反的模式,因为finally()
方法首先附加,订阅强制强制通过/失败。
是的,这太糟糕了。有人会认为 finally
块将在您的代码中排在最后。
我喜欢 Angular JS 的承诺系统......正如 d512 所说,我希望“终于”成为最后一个......根本不喜欢这个......
从 RXJS 5.5 开始,“finally”不再是 Observable 方法。请改用“finalize”运算符: source.pipe(finalize(() => console.log('Finally callback'))).subscribe(...); github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
finalize 的问题是它等待“complete()”调用。如果您希望在每次发射时都得到最终结果(如果可观察到的发射成功,请执行 a,如果出错,请执行 b 代替 .. 在这两种情况下,请执行 c )?【参考方案3】:
唯一对我有用的是这个
fetchData()
.subscribe(
(data) =>
//Called when success
,
(error) =>
//Called when error
).add(() =>
//Called when operation is complete (both success and error)
);
【讨论】:
我在删除文件订阅后使用它来获取表数据,效果很好,谢谢!以上是关于在订阅上最终可观察到的主要内容,如果未能解决你的问题,请参考以下文章
如果两个依赖路径改变为可观察的,则Knockout在单个动作上计算多次触发