angular2/rxjs ngUnsubscribe:如何退订所有与装饰订阅?
问题描述:
基于编辑3 here我实现了该解决方案。但是,在每个组件中进行主题初始化和“清理”ngOnDestroy仍然很痛苦。我认为它可以传递给装饰者,例如。基于此post:angular2/rxjs ngUnsubscribe:如何退订所有与装饰订阅?
export function AutoUnsubscribe(constructor) {
const original = constructor.prototype.ngOnDestroy;
constructor.prototype.ngUnsubscribe = new Subject<void>();
constructor.prototype.ngOnDestroy = function() {
constructor.prototype.ngUnsubscribe.next();
constructor.prototype.ngUnsubscribe.complete();
original && typeof original === "function" && original.apply(this, arguments);
};
}
用法与其他类装饰器一样。它运行良好,但我不得不在使用类型系统时,像这样:takeUntil((this as any).ngUnsubscribe)
。
属性ngUnsubscribe无法识别组件中的类型系统。有什么方法可以告诉类型系统该属性是否存在或将会存在?
如果这样做可能会很容易使用这个@AutoUnsubscribe装饰器:只需装饰一个类,并在每次订阅前放置takeUntil(this.ngUnsubscribe)。不知道如果我们可以做得更好,只是装饰一个类,并自动地这个装饰器将在每次订阅我们之前将takeUntil(this.ngUnsubscribe)。
我目前的解决方法是使用BaseComponent与ngUnsubscribe道具。并扩展每个调用订阅的组件。
答
也许我将使用过的模型的例子,但我认为有两种方法可以做到这一点:
创建只是告诉编译器对类属性的接口
延长模块的属性相匹配的文件名,并添加到界面
1.创建一个接口
export interface MyOtherClass {
magicProperty: string;
}
export class MyOtherClass
{
func(): void {
console.log(this.magicProperty);
}
}
2.扩展模块
// 43479078.ts
export class MyOtherClass
{
func(): void {
console.log(this.magicProperty);
}
}
...和
// MyOtherClass-extension.d.ts
import { MyOtherClass } from './43479078';
declare module './43479078' {
interface MyOtherClass {
magicProperty: void;
}
}
要知道,现在编译时,你需要包含两个文件或添加/// <reference path="./MyOtherClass-extension.d.ts" />
在43479078.ts
的顶部。
此外,我认为扩展类需要导出,否则该文件不会被视为一个模块。
发现这很难:如果在编译时ngOnDestroy在组件上不存在,ng buld --prod --aot会优化掉任何对ngOnDestroy的调用,即使该方法在运行时可用。解决方案:使用@AutoUnsubscribe时始终有一个ngOnDestroy,即使它是空的 –