简体   繁体   English

如果我重新分配一个存储 rxjs 订阅的变量,会取消订阅吗?

[英]If I reassign a variable which stores an rxjs subscription, does that unsubscribe?

Here's a prototype of my code in Angular:这是我在 Angular 中的代码原型:

import { Subscription } from 'rxjs';
import { SomeClass, SomeOtherClass } from './my-component.model.ts';
import { OnDestroy } from '@angular/core';

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.scss'],
})
export class AnalysisToolsComponent implements OnDestroy {
    private sub: Subscription;
    // instance of some class I defined in my models which has an event emitter
    instance = new SomeClass();

    // this function might get called more than once
    someFunction() {
        sub = this.instance.onEvent.subscribe( () => {})
    }

    // some other function which results in a reassignment of instance to maybe some other class
    someOtherFunction() {
        instance = new SomeOtherClass();
    }

    ngOnDestroy() {
        if (this.sub) {
            this.sub.unsubscribe();
        }
    }
}

Someone might ask why I'm reassigning the sub.有人可能会问为什么我要重新分配 sub。 It's basically because I have a child component which is a tool bar where only one tool can be selected at a time.这基本上是因为我有一个子组件,它是一个工具栏,一次只能选择一个工具。 So I only need one sub at a time to listen to events from interactions with the toolbar.所以我一次只需要一个 sub 来监听与工具栏交互的事件。

Should I be unsubbing each time I switch tool?每次切换工具时我都应该取消订阅吗? Or can I just reassign the sub variable?或者我可以重新分配sub变量吗? My hypothesis is that the former is true.我的假设是前者是正确的。 So might be nice to also get the explanation behind it if you have the answer.因此,如果您有答案,也可以得到其背后的解释。

Switching to a new Observable and automatically unsubscribing from the old one is best done with switchMap .最好使用switchMap切换到新的 Observable 并自动取消订阅旧的switchMap To unsubscribe from an Observable when the Component gets destroyed use the takeUntil-destroy pattern.要在组件被销毁时取消订阅 Observable,请使用 takeUntil-destroy 模式。

tool$ = new BehaviorSubject<SomeTool>(new SomeTool());
private destroy$ = new Subject();

ngOnInit() {
  this.tool$.pipe(
    // use switchMap to map to a new onEvent Observable and unsubscribe from the old one
    switchMap(tool => tool.onEvent),
    // use takeUntil pattern to unsubscribe from tool$ when the component gets destroyed 
    takeUntil(this.destroy$)  
  ).subscribe( () => {} )
}

switchTool() {
  // supply a new Observable or Object containing an Observable to your Subject
  this.tool$.next(new SomeOtherTool());  // presuming SomeOtherTool extends SomeTool
}

ngOnDestroy() {
  this.destroy$.next();
  this.destroy$.complete();
}

you can unsubscribe something like below,您可以取消订阅如下内容,

private sub: Subscription[] = [];

...
this.sub.push(this.instance.onEvent.subscribe( () => {}));
...

ngOnDestroy() {
  // prevent memory leak when component destroyed
  this.subscriptions.forEach(s => s.unsubscribe());
}

can I just reassign the sub variable?我可以重新分配子变量吗?

It's not needed with this approach这种方法不需要

It will unsubscribe() all the subscriptions held by the Subscription .它将unsubscribe() subscriptions持有的所有Subscription

Are all of these observables being created in the component?所有这些 observable 都是在组件中创建的吗? If so then when the component is destroyed then all the properties fall into garbage collection with it.如果是这样,那么当组件被销毁时,所有属性都会随之进入垃圾收集。 You get memory leaks from subscription to observables that are not garbage collected at the same time the component is destroyed.您会从订阅到 observable 的内存泄漏,这些 observable 不是在组件被销毁的同时被垃圾收集的。

If your component instantiates an observable and nothing else is holding a reference to that observable then unsubscribing is unnecessary as the observable falls into garbage collection with the component.如果您的组件实例化了一个 observable 并且没有其他任何东西持有对该 observable 的引用,那么取消订阅是不必要的,因为 observable 会与组件一起进入垃圾收集。

An observable that still has active references like in a service will cause memory leaks if your component is still subscribed and the component cannot be garbage collected as the subscriptions are still active on the observable in the service.如果您的组件仍然被订阅并且组件不能被垃圾收集,因为订阅在服务中的 observable 上仍然处于活动状态,那么在服务中仍然具有活动引用的 observable 将导致内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM