ionic4-subscribe manage(訂閱管理)

node 10.15.0
ionic 4.12.0
cordova 9.0
# platforms
cordova-android:8.0.0
cordova-ios: 5.0.0

為什么要管理訂閱?

問(wèn)題一:Memory leak

場(chǎng)景:
頁(yè)面操作順序:TestPage -> Test2Page ->(返回到) TestPage
Test2Page中模擬接口請(qǐng)求,發(fā)射數(shù)據(jù)并訂閱
Chrome Memory 實(shí)驗(yàn)結(jié)果如下:

in TestPage

image.png

in Test2Page

image.png

back TestPage

image.png

此時(shí)Test2Page仍在內(nèi)存中。

解決:在OnDestory()取消訂閱

export class Test2Page implements OnInit, OnDestroy {
  subs: Subscription;
  msgData = 'xxxxx2';
  constructor() {
  }
  ngOnInit() {
    this.subs = this.makeData()
      .pipe(delay(5000))
      .subscribe(
        data => {
          console.log('makeData2 -> data = ' + data[0].name);
          this.msgData = data[0].name;
        },
        error2 => console.log('makeData2 -> error = ' + error2)
      );
  }
  makeData(): Observable<any> {
    return of([{id: 1, name: 'BBB'}]);
  }
  ngOnDestroy(): void {
    this.subs.unsubscribe();
  }
}

驗(yàn)證效果


image.png

問(wèn)題二:Html render

場(chǎng)景和問(wèn)題一一樣,只是此時(shí)Test2Page頁(yè)面數(shù)據(jù)源慢尚未返回,操作返回到TestPage,
回到TestPage后,接口數(shù)據(jù)到了,由于未取消訂閱,所以會(huì)繼續(xù)執(zhí)行處理數(shù)據(jù)方法,然后渲染頁(yè)面,但此時(shí)Test2Page頁(yè)面已被銷毀,無(wú)法渲染。


image.png

實(shí)現(xiàn)訂閱管理

定義SubSink類

_subs: SubscriptionLike[] 存儲(chǔ)訂閱對(duì)象,便于取消訂閱

const isFunction = (fn: any) => typeof fn === 'function';

export interface SubscriptionLike {
  unsubscribe(): void;
}

export class SubSink {

  protected _subs: SubscriptionLike[] = [];

  constructor() {
  }

  add(...subscriptions: SubscriptionLike[]) {
    this._subs = this._subs.concat(subscriptions);
  }

  set sink(subscription: SubscriptionLike) {
    this._subs.push(subscription);
  }

  unsubscribe() {
    this._subs.forEach(sub => sub && isFunction(sub.unsubscribe) && sub.unsubscribe());
    this._subs = [];
  }
}

定義BaseComponent類

BaseComponent實(shí)現(xiàn)OnDestroy方法,及組件銷毀時(shí)取消訂閱

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

  /**
   * Component銷毀時(shí)會(huì)取消訂閱
   */
  ngOnDestroy(): void {
    this.subs.unsubscribe();
  }
}

使用

首先繼承BaseComponent;
其次構(gòu)造方法:super();
最后將訂閱對(duì)象賦值給 this.subs.sink,此時(shí)會(huì)調(diào)用SubSink類中的
this._subs.push(subscription);

export class Test2Page extends BaseComponent implements OnInit {
  msgData = 'xxxxx2';

  constructor(private changeRef: ChangeDetectorRef) {
    super();
  }

  ngOnInit() {
    this.subs.sink = this.makeData()
      .pipe(delay(5000))
      .subscribe(
        data => {
          console.log('makeData2 -> data = ' + data[0].name);
          this.msgData = data[0].name;
          this.changeRef.detectChanges();
        },
        error2 => console.log('makeData2 -> error = ' + error2)
      );
  }

  makeData(): Observable<any> {
    return of([{id: 1, name: 'BBB'}]);
  }

}

測(cè)試

image.png

參考文獻(xiàn)

how-to-automatically-unsubscribe

總結(jié)

總的來(lái)說(shuō),取消訂閱還是很有必要的;通過(guò)上面的方式,極大程度的方便了使用。

下一篇將介紹全局異常處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容