美文网首页ionic4 混合开发实战
ionic4-subscribe manage(订阅管理)

ionic4-subscribe manage(订阅管理)

作者: SandLZ | 来源:发表于2019-05-07 16:58 被阅读0次
    node 10.15.0
    ionic 4.12.0
    cordova 9.0
    # platforms
    cordova-android:8.0.0
    cordova-ios: 5.0.0
    

    为什么要管理订阅?

    问题一: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-subscribe manage(订阅管理)

        本文链接:https://www.haomeiwen.com/subject/qyfyoqtx.html