簡體   English   中英

Angular 清除訂閱的更好方法

[英]Angular better way to clear subscriptions

有很多方法可以在一個組件中有效地處理多個訂閱,我這里有兩種方法,想知道哪種方法更有效,為什么?

方法一:使用數組

第 1 步:創建數組

private subscriptionArray: Subscription[];

第 2 步:向數組添加訂閱

this.subscriptionArray.push(this._storeManagementHttp.createStore(newStore).subscribe(resp => {
  this._toast.success('New store created');
}));

步驟 3:迭代每個訂閱和取消訂閱

this.subscriptionArray.forEach(subs => subs.unsubscribe());

方法二

第 1 步:創建新訂閱

private subscriptions = new Subscription();

第 2 步:添加訂閱

this.subscriptions.add(this._storeManagementHttp.createStore(newStore).subscribe(resp => {
  this._toast.success('New store created');
  this._router.navigate(['/store-management']);
}));

Step3:清除訂閱

this.subscriptions.unsubscribe();

你也可以這個,在這種情況下你不需要運行循環

    private destroy$ = new Subject();
    
    myservice.megohd().pipe(takeUntil(destroy$)).subscribe();
    
    ngOnDestroy() {
      this.destroy$.next();
      this.destroy$.complete();
    }

在這里閱讀( https://www.learnrxjs.io/operators/filtering/takeuntil.html

您還有第三個選項,即自定義 RxJS 運算符。

我創建了一個,發現Netanel Basal也找到了它,所以我會給出他的干凈代碼。

您可以安裝UntilDestroyed或使用代碼:

function isFunction(value) {
  return typeof value === 'function';
}

export const untilDestroyed = (
  componentInstance,
  destroyMethodName = 'ngOnDestroy'
) => <T>(source: Observable<T>) => {
  const originalDestroy = componentInstance[destroyMethodName];
  if (isFunction(originalDestroy) === false) {
    throw new Error(
      `${
        componentInstance.constructor.name
      } is using untilDestroyed but doesn't implement ${destroyMethodName}`
    );
  }
  if (!componentInstance['__takeUntilDestroy']) {
    componentInstance['__takeUntilDestroy'] = new Subject();

    componentInstance[destroyMethodName] = function() {
      isFunction(originalDestroy) && originalDestroy.apply(this, arguments);
      componentInstance['__takeUntilDestroy'].next(true);
      componentInstance['__takeUntilDestroy'].complete();
    };
  }
  return source.pipe(takeUntil<T>(componentInstance['__takeUntilDestroy']));
};

然后你的訂閱變成

this.myService.subject.pipe(untilDestroyed(this)).subscribe(...);

請注意,由於 AOT 編譯,您必須編寫一個ngOnDestroy方法,否則操作員無法從頭開始創建它。

有更好、更簡潔的解決方案:Ward Bell 的https://www.npmjs.com/package/subsink

export class SomeComponent implements OnDestroy {
  private subs = new SubSink();

  ...
  this.subs.sink = observable$.subscribe(...);
  this.subs.sink = observable$.subscribe(...);
  this.subs.sink = observable$.subscribe(...);
  ...

  // Unsubscribe when the component dies
  ngOnDestroy() {
    this.subs.unsubscribe();
  }
}

我更喜歡方法2。

在方法1上沒有問題。

它工作得很好。 這種方法的問題是我們將可觀察的流與普通的舊命令式邏輯混合在一起。

方法 2 是增強此方法的內置機制。

在這里閱讀

盡管我會盡可能避免使用上述所有方法並使用async 'pipe,但您提供了很好的答案,即允許 Angular 進行訂閱和取消訂閱。

讓我們考慮一些 Observables 說 5 observables

observale1$: Observable<IDataDto1>;
observale2$: Observable<IDataDto2>;
observale3$: Observable<IDataDto3>;
observale4$: Observable<IDataDto4>;
observale5$: Observable<IDataDto5>;

為了避免訂閱所有這些,我們可以創建一個單獨的Observable比如說v$


import { forkJoin } from 'rxjs';
v$ = forkJoin({
  observale1: observale1$,
  observale2: observale2$,
  observale3: observale3$,
  observale4: observale4$,
  observale5: observale5$
});

有了上面的內容,我們可以將component.html包裝在*ngIf中,並允許 Angular 自動訂閱和取消訂閱


<ng-container *ngIf='v$ | async as v'>
  <!-- Your html code here -->
</ng-container>

方法 2 因為Subscription.unsubscribe()不僅僅是看似取消訂閱, 請在此處查看其源代碼

例如


class SomeClass implements OnInit, OnDestroy { {

  // Setup your subscriptions
  private subscriptions = new Subscription();

  // Example Observable service
  constructor(private someService: SomeService) {}

  ngOnInit(): void {
    this.subscriptions.add(this.someService.getStuff());
    // ...
    this.subscriptions.add(/* etc */);
  }

  ngOnDestroy() {
    this.subscriptions.unsubscribe();
  }

} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM