Angular: 适当的退订时间

Angular: Proper time to unsubscribe

使用网络服务时,什么时候退订最好?在我的代码中我一直在这样做

tempFunction() {
    const temp = this.myService.getById(id).subscribe(
        response => this.model = response,
        error => console.error(error),
        final => temp.unsubscribe() // unsubscribe here
    );
}

但在其他地方,我看到过这个

temp: any;

tempFunction() {
    temp = this.myService.getById(id).subscribe(
        response => this.model = response,
        error => console.error(error),
        final => {}
    );
}

ngOnDestroy() {
    this.temp.unsubscribe(); // vs unsubscribe here
}

我退订的方式与其他人退订的方式在功能上有区别吗?

您不需要像以前那样取消订阅简单的网络请求。他们只会开火一次,然后会为您处理退订事宜。 Here is a SO question 讨论了这个主题以及为什么没有必要。

作为如何取消订阅的一般主题,最好的方法往往是使用 this pattern 或使用 takeUntil。这使您可以确保在以最干净的方式销毁组件时清除所有内容(无需保留多个订阅并在每个订阅上调用 unsubscribe)。

import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/takeUntil';

@Component({ ... })
export class ExampleComponent implements OnInit, OnDestroy {
    destroy$: Subject<boolean> = new Subject<boolean>();

    ngOnInit() {
        this.someMethodThatReturnsObservable(...)
            .takeUntil(this.destroy$)
            .subscribe(...);

        this.someOtherMethodThatReturnsObservable(...)
            .takeUntil(this.destroy$)
            .subscribe(...);
    }

    ngOnDestroy() {
        this.destroy$.next(true);
        // Now let's also unsubscribe from the subject itself:
        this.destroy$.unsubscribe();
    }
}

何时退订取决于订阅的内容以及您实际使用它的方式。在您的示例中,当 Observable 完成 时,您正在调用 .unsubscribe。您不需要这样做,因为当 Observable 完成后它将不再发射。相反,如果 Observable 在您可能不再需要它之后继续发射,则您需要取消订阅,例如当离开你的组件时。这就是为什么您看到 ngOnDestroy 用于处理订阅。

通常您希望避免调用 .unsubscribe。参见:https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87

还有其他方法可以处理订阅,例如使用 take 方法。 Angular 也有非常强大的 async pipe 允许您在模板中使用 Observables 并为您处理退订。

用一些例子来回顾一下:

// No need to unsubscribe here. Http Observables only emit once
this.serviceUsingHttp.get().subscribe(useResponse);

// Allows you to call `.unsubscribe` in case the subscription wasn't created properly
events = new Subscription();
ngOnInit() {
  this.events = fromEvent(document, 'someEvent').subscribe(useEvent);
}
ngOnDestroy() {
  this.events.unsubscribe();
}

destroyed$ = new Subject();
ngOnInit() {
  fromEvent(document, 'resize').pipe(takeUntil(this.destroyed$)).subscribe(useResize);
  fromEvent(document, 'scroll').pipe(takeUntil(this.destroyed$)).subscribe(useScroll);
  fromEvent(document, 'change').pipe(takeUntil(this.destroyed$)).subscribe(useChange);
}
ngOnDestroy() {
  // Complete all of the event observables at once.
  this.destroyed$.next(true);
  this.destroyed$.complete();
}

答案是:完成订阅后取消订阅。如果它需要在组件的整个生命周期内都处于活动状态,那么在 ngOnDestroy 中取消订阅是合适的。如果您只需要来自 observable 的一个输出,那么在 .subscribe() 回调中取消订阅是有意义的。如果您应用中的某些其他情况可能意味着在任意时间不再需要订阅,请随时在需要时取消订阅。

唯一的规则是"Don't forget to unsubscribe."关于何时执行没有硬性规定。