如何确保我取消订阅?

Posted

技术标签:

【中文标题】如何确保我取消订阅?【英文标题】:How do I make sure that I unsubscribed subscribe? 【发布时间】:2022-01-16 21:14:40 【问题描述】:

我有一个订阅,我从商店获取一些消息以输出 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();
  

【问题讨论】:

【参考方案1】:

我认为您可以在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();
  

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

Angular RxJS Observable: takeUntil vs. unsubscribe with a Subscription

【讨论】:

【参考方案2】:

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

如果您想确保取消订阅确实发生,您可以在ngOnDestroy 方法中添加日志或在浏览器中调试它。

【讨论】:

【参考方案3】:
    一开始不要这样写使用Services。 您可以像本例中一样使用 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();
  

【讨论】:

【参考方案4】:

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

或者您可以使用类似我提出的演示 here 进行调试。通过显示/隐藏子组件,您可以看到正在记录“ping”消息的订阅,并相应地启动和停止。

【讨论】:

以上是关于如何确保我取消订阅?的主要内容,如果未能解决你的问题,请参考以下文章

嵌套可观察订阅问题,无法取消订阅

如何:取消订阅 Apollo (subscribeToMore) 订阅?

我如何在反应中取消订阅

如何获得自动续订订阅的取消日期?

如何在 RxSwift 中取消订阅 Observable?

如何取消我的 Microsoft Azure 订阅?