gpt4 book ai didi

angular - 为 takeUntil 运算符提供的哪种方法更适合杀死可观察对象,为什么?

转载 作者:太空狗 更新时间:2023-10-29 17:41:05 29 4
gpt4 key购买 nike

我有一个关于使用 takeUntil 运算符取消订阅 Angular 和 RxJs 的常见模式的问题。在 this article ,它在第三个位置下。比如我们在一个组件类中有这样的代码:

  private destroy$: Subject<boolean> = new Subject();

ngOnInit() {
this.control.
.pipe(takeUntil(this.destroy$)
.subscribe(doSmthngFunc);
}

ngOnDestroy() {
this.destroy$.next(true);
// Which next line of code is correct?
// this.destroy$.complete() // this one?
// this.destroy$.unsubscribe() // or this one?
}

第一行 this.destroy$.next(true) 非常清楚。但第二个不是。如果我们研究这些方法的实现,我们会发现它们有一些相似的行为。 complete(): unsubscribe():

据我了解语义上 complete() 更可取,因为我们在组件生命周期中第一次也是最后一次调用 next(),然后我们完成了这个 Subject,被视为 Observable 并且可以调用 complete()。这些方法属于观察者,取消订阅属于可观察对象,我们没有订阅可以取消订阅。但在幕后,这些方法具有相似的代码:

    this.isStopped = true; // both

this.observers.length = 0; // complete
this.observers = null; // unsubscribe

this.closed = true; // only unsubscribe

理论上 complete() 具有延迟效果,因为它可能会在每个订阅的观察者上调用 complete(),但我们在 destroy$ 上没有观察者。那么问题来了 - 哪种方式更可取、更不容易出错,为什么?

最佳答案

组件的销毁是一个单一事件。

   this.destroy$.next();
this.destroy$.complete();

确保主题只发出一次并且完成

例如;

    const destroy$ = new Subject();

destroy$.subscribe(v => console.log("destroyed"));

destroy$.next();
destroy$.complete();
destroy$.next();

// the above prints "destroyed" only once.

完成不是技术要求,但如果您不这样做,那么依赖于完成而不是发射的业务逻辑将不会始终有效,并且可能会泄漏内存。

例如,以下将是 RxJs 中的内存泄漏。

   destroyed$.subscribe(() => {
console.log('This might leak memory');
});

上面的内容可能会泄漏内存,因为订阅永远不会结束,而可观察对象永远不会完成。您可以通过添加 first() 运算符或确保主题已完成来修复泄漏。 RxJS 不知道主题只会发出一个值,所以你必须告诉它。否则订阅者仍然绑定(bind)到堆栈帧并且不会被垃圾收集。因此,虽然垃圾收集器可能会在组件使用后收集组件,但如果有任何内容引用了订阅者的堆栈框架,那么该订阅将继续存在。

因此,在您的销毁对象上调用完成,这样其他人就不会犯错误。

this.destroy$.unsubscribe()

在主题上调用取消订阅 可能不会对创建内部 订阅的下游运算符产生影响。例如,switchMap()mergeMap() 创建内部订阅。

因此您无法有效地管理更高级别的订阅。最好从调用 subscribe() 方法时创建的订阅中取消订阅,因为这是运算符链中的最后一个。

关于angular - 为 takeUntil 运算符提供的哪种方法更适合杀死可观察对象,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56908956/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com