确保派生组件中的 super.onDestroy()

Lie*_*ero 8 inheritance typescript angular

我有一堆生命周期逻辑非常相似的组件,所以我创建了我的基本组件,它实现了 OnDestroy

abstract class BaseComponent implements OnDestroy {
   subscriptions = new Array<Subscription>();
   get model() { return … }

   ngOnDestroy() {
      for (let s of subscriptions) s.unsubscribe();
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,当开发人员在 extends 的具体 Component 中编写自定义 onOnDestroy 方法时ComponentBase,他无法知道他需要调用super.ngOnDestroy();

是否有一些(打字稿)方法来确保警告?或者模式其他组件继承?也许是一个单元测试,可以测试ngOnDestroy所有扩展的组件BaseComponent?

编辑 我得出结论,BaseComponent上面的订阅数组是一种常见的反模式,应该避免。理想情况下使用自动取消订阅可观察对象。

看到这个 takeUntil(destroy$) 模式:

class MyComponent implements OnInit, OnDestroy {    
    destroy$ = new Subject();    
  
    constructor(http: HttpService) { }

    ngOnInit() {
        http.get(...).pipe(
          takeUntil(this.destroy$)
        ).subscribe(...);  
    }
    

    ngOnDestroy() {
      onDestroy$.onNext();
   }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*idt 7

最简单的解决方案是定义一个ngOnDestroy孩子也需要返回的返回类型。

class REQUIRED_SUPER {} //important to not export it, only we should be able to create it.

class Base implements OnDestroy {
    ngOnDestroy(): REQUIRED_SUPER {
        return new REQUIRED_SUPER;
    }
}

Run Code Online (Sandbox Code Playgroud)

因此,如果您的用户也没有返回它,则意味着他没有调用您的方法。

export class Child extends Base implements OnDestroy {
    ngOnDestroy(): REQUIRED_SUPER {
    }
}
Run Code Online (Sandbox Code Playgroud)

这将导致 TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.

要解决它,您的用户需要这样做:

ngOnDestroy(): REQUIRED_SUPER {
    return super.ngOnDestroy();
}
Run Code Online (Sandbox Code Playgroud)

或者

ngOnDestroy(): REQUIRED_SUPER {
    const superCalled = super.ngOnDestroy();
    //to stuff
    return superCalled;
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*eep 5

我知道它晚了..但对于需要它的人.!!!

export abstract class BaseClass implements OnDestroy {

ngOnDestroy(): void { }

constructor() {
    const refOnDestroy = this.ngOnDestroy;
    this.ngOnDestroy = () => {
        refOnDestroy();
       // perform unsubscriptions here
       // eg: for (let s of subscriptions) s.unsubscribe();
    };
 }
}
Run Code Online (Sandbox Code Playgroud)

详细说明可以在这里找到


小智 -1

您可以确保开发人员永远不会subscribe在组件中编写 a ,这样就无需取消订阅。

这意味着您将充分利用反应式编程,包括 rxjs 运算符和异步管道。

您还可以使用自定义类装饰器来测试所有类成员并查看它们是否是订阅的实例。

您最终可以使用自定义 rxjs 运算符,一旦您的组件被销毁,该运算符就会取消订阅。

它们有多个可用选项,但我建议使用第一个,因为它使您的代码更清晰并易于读取 onPush 更改检测策略。