我如何确保我取消订阅?

How do I make sure that I unsubscribed subscribe?

我有一个订阅,我从商店获取一些消息以输出 toastr。

我通过订阅.unsubscribe()退订了。

如何检查我是否真的退订了?

  subscription!: Subscription;

  ngOnInit(): void { }

  toastrError(): void {
    this.subscription = this.store.select(getMessage).subscribe(m => {
      (m.message && m.title) ? this.toastr.error(m.message, m.title) : null;
    });
  }

  singIn(): void {
    this.toastrError();
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }

我猜如果不再出现错误提示,您可能会看到您已取消订阅。但我明白你的意思。您可以记录 ngOnDestroy 方法以确保它 运行 并因此取消订阅。

或者您可以使用我提出的演示之类的东西来调试它 here。通过 showing/hiding 子组件,您可以看到正在记录 'ping' 消息的订阅,相应地启动和停止。

  1. 一开始不要这样写使用服务
  2. 您可以像本例中那样使用 takeUntil。

import { Component, OnDestroy, OnInit } from '@angular/core';
// RxJs 6.x+ import paths
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { BookService } from '../books.service';

@Component({
  selector: 'app-books',
  templateUrl: './books.component.html'
})
export class BooksComponent implements OnDestroy, OnInit {
  private ngUnsubscribe = new Subject();

  constructor(private booksService: BookService) { }

  ngOnInit() {
    this.booksService.getBooks()
      .pipe(
        startWith([]),
        filter(books => books.length > 0),
        takeUntil(this.ngUnsubscribe)
      )
      .subscribe(books => console.log(books));

    this.booksService.getArchivedBooks()
      .pipe(takeUntil(this.ngUnsubscribe))
      .subscribe(archivedBooks => console.log(archivedBooks));
  }

  ngOnDestroy() {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }
}

组件实例的生命周期始于 Angular 实例化组件 class 并呈现组件视图(及其子视图)。生命周期继续进行一些更改检测,因为 Angular 检查以查看数据绑定属性何时更改,并在需要时更新视图和组件实例作为响应。当 Angular 实际销毁组件实例并从 DOM 中删除其呈现的模板时,生命周期结束,因此 ngOnDestroy 在 Angular 销毁组件(或指令)之前立即被调用.

如果你想确认取消订阅是否真的发生,你可以在ngOnDestroy方法中添加一个日志,或者在浏览器中调试它。

我认为您可以在 unsubscribe() 之后使用 closed 标志来验证它。例如

if(!this.subscription.closed)
      console.error("Some error unsubscribing ?!");

如果您的意思是在组件外部进行验证,那么您可能无法执行此操作,因为 ngOnDestroy 只会在组件实例销毁之前调用。您可能会尝试在此处发出事件,但可能会迟到检查它!

但是,作为一种好的做法,您可以在组件中定义一个 subject,并使用它来取消所有使用 takeUntil() 的订阅。例如

export class LoginComponent implements OnInit, OnDestroy {

  private destroy$ = new Subject<void>();

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.http.get("http://whatever")
      .pipe(takeUntil(this.destroy$))
      .subscribe(value => console.log(value));
  }

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

检查此问题以了解这些方法之间的区别