ionic4-Subscribe manage(订阅管理)

本文介绍了在Ionic4应用中管理订阅以避免内存泄漏和优化HTML渲染的问题。当从TestPage转到Test2Page再返回时,未取消订阅会导致内存占用。解决方案是在组件销毁时取消订阅。此外,如果Test2Page的数据延迟返回,未取消订阅会继续渲染已销毁的页面。通过定义SubSink和BaseComponent类,可以便捷地管理订阅并在组件销毁时自动取消。

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

欢迎访问我的专栏:
ionic4 混合开发实战-csdn
ionic4 混合开发实战-简书

为什么要管理订阅?

问题一:Memory leak

场景:
页面操作顺序:TestPage -> Test2Page ->(返回到) TestPage
Test2Page中模拟接口请求,发射数据并订阅
Chrome Memory 实验结果如下:

in TestPage

image.png

in Test2Page

image.png

back TestPage

image.png
此时Test2Page仍在内存中。

解决:在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();
  }
}

验证效果
image.png

问题二:Html render

场景和问题一一样,只是此时Test2Page页面数据源慢尚未返回,操作返回到TestPage,
回到TestPage后,接口数据到了,由于未取消订阅,所以会继续执行处理数据方法,然后渲染页面,但此时Test2Page页面已被销毁,无法渲染。
image.png

实现订阅管理

定义SubSink类

_subs: SubscriptionLike[] 存储订阅对象,便于取消订阅

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实现OnDestroy方法,及组件销毁时取消订阅

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

  /**
   * Component销毁时会取消订阅
   */
  ngOnDestroy(): void {
    this.subs.unsubscribe();
  }
}

使用

首先继承BaseComponent;
其次构造方法:super();
最后将订阅对象赋值给 this.subs.sink,此时会调用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'}]);
  }

}

测试

image.png

参考文献

how-to-automatically-unsubscribe

总结

总的来说,取消订阅还是很有必要的;通过上面的方式,极大程度的方便了使用。

下一篇将介绍全局异常处理。

欢迎访问我的专栏:
ionic4 混合开发实战-csdn
ionic4 混合开发实战-简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值