.unsubscribe和.take(1)的区别

118

我想知道,在订阅后立即使用 .unsubscribe.take(1) 有没有性能上的区别:

var observable = Rx.Observable.interval(100);

首先:

var subscription = observable.subscribe(function(value) {
   console.log(value);
}).unsubscribe();

其次:

var subscription = observable.take(1).subscribe(function(value) {
    console.log(value);
});

任何对于它是否对性能有任何不同的想法吗?


6
如果在 JavaScript 执行这行代码后,函数 A 仍然被调用,那么 var subscription = observable.subscribe({function A}).unsubscribe(); 不会按预期工作。因此,你将得到零值而不是一个值。建议手动订阅并使用 take(..) 或其他像 take 这样处理订阅的方法。 - Stav Alfi
2个回答

176

每个工具都有其不同的用途,因此很难进行比较。

一般来说,如果您使用此源:

const source = range(1,3);

使用 subscribe() 订阅并立即使用 unsubscribe() 取消订阅:

source.subscribe(
  console.log,
  undefined, 
  () => console.log('complete')
).unsubscribe();

即使我们在订阅后立即调用unsubscribe(),如果代码仍然是严格顺序(同步)的且source是冷Observable,则所有来自source 的值都会被发出。

1
2
3
complete

另外,尝试添加delay(0)操作符以使source.pipe(delay(0)).subscribe(...).unsubscribe()中的值发射变为异步,使用真实的setTimeout()调用。因此,在任何next处理程序之前,调用unsubscribe()并立即丢弃它。

换句话说,unsubscribe()可以让您随时停止接收值。即使源未发出任何值(我们永远不会收到任何完成通知)。

使用take()操作符限制链只发出特定数量的值。

source.pipe(
  take(1),
)
.subscribe(
  console.log,
  undefined,
  () => console.log('complete')
);

这只会发出单个值并完成:

1
complete
即使添加了.unsubscribe(),结果仍然相同。查看现场演示:https://stackblitz.com/edit/rxjs-tbu5kb。因此,take()是一个操作符,而unsubscribe()Subscription对象上的方法。这两个东西通常可以互换,但它们永远无法完全替代彼此。更新日期:2019年1月,适用于RxJS 6。

81
嗨 @martin,take(1)会取消订阅吗?如果我加上take(1),我还需要调用unsubscribe吗?谢谢。 - fifth
135
不需要。当链式操作完成后,它会递归地调用所有的处理程序,所以你不需要自己调用 unsubscribe - martin
13
第五条,@martin - 你能否将这两个评论制作成一个问答形式?我实际上正在寻找这个具体问题('does take-1 do unsubscribe?'),并意外地进入了这个问题。从您的评论中不同寻常的高赞数来看,其他人似乎也同意;)或者至少以某种明显的方式将其添加/插入到当前的问答中。 take-X(或流的任何“完成”)确实进行退订是非常重要的事实,我找不到任何可以涉及此事并像Martin在这里的评论中那样给出明确和清晰答案的问答。 - quetzalcoatl
2
@quetzalcoatl 如果你查看源代码,它会调用unsubscribe。https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/take.ts#L95 - Tengis
1
请注意,如果因任何原因它无法取消订阅一个(或任意数量的计数),请小心。 - Farhad

64

而取消订阅的解决方案是什么? 不要使用take,而是用takeUntil(this.destroyable$)替换它,this.destroyable$是在单独组件中的subject,将在ngOnDestroy中进行next操作。 - pinarella
@pinarella,那篇文章提供了几种潜在的解决方案,包括在组件被销毁时取消订阅的最常用方法。如果你需要针对某个特定解决方案寻求帮助,请创建一个问题并发布完整细节。 - kh42874

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接