【问题标题】: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();
  }

【问题讨论】:

    标签: angular ngrx


    【解决方案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】:
        1. 一开始不要这样写使用Services。
        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();
          }
        }

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-19
            • 2012-03-14
            • 2017-02-12
            • 2019-12-05
            • 1970-01-01
            • 1970-01-01
            • 2015-08-24
            • 2015-07-16
            相关资源
            最近更新 更多