首页 > 解决方案 > 为什么在 RxJS 中解除了 finalize?

问题描述

我无法理解RxJS 中的finalize运算符。让我用一个例子来证明这一点:

of(null).pipe(
  tap({ complete: () => console.log('tap 1 completes') }),
  finalize(() => console.log('finalize')),
  tap({ complete: () => console.log('tap 2 completes') })
).subscribe({ complete: () => console.log('subscribe completes') });

我希望finalize回调在第二个之前执行tap。不过,这并没有发生。而是上面的代码产生以下输出:

tap 1 completes
tap 2 completes
subscribe completes
finalize

查看实现,我相信操作员通过整个可观察链传递(提升)以始终在其末端应用。所以现在我有两个问题:

  1. 这个设计决策背后的基本原理是什么?你能解释一下为什么这是一个理想/有利的属性吗?
  2. 是否有不同的运算符或其他解决方案可以在完整和错误时执行代码,但按顺序(即在tap上面示例中的第二个之前)而不是在可观察链的末尾?

标签: rxjs

解决方案


重要的是要意识到这一点finalize()并以tap()非常不同的方式工作。tap()由 触发next,通知 whileerror仅在链订阅时触发。换句话说,与使用非常相似:completefinalize()finalize()

const subscription = $source.subscribe();
// This will be always triggered after all `tap()`s
subscription.add(() => console.log('same as finalize()'));

所以你不能finalize()在之前被调用tap()。另外,请注意,finalize()当您手动取消订阅时也会调用以下内容:

subscription.unsubscribe(); // will always invoke `finalize()` but never `tap()`

一种可能的解决方案可能是实现您自己的finalize()变体,该变体知道它被调用的原因:https ://github.com/martinsik/rxjs-extra/blob/master/doc/finalizeWithReason.md (参见源代码)

另请注意,https://github.com/ReactiveX/rxjs/pull/5433不会影响您的用例。


推荐阅读