我创建了一个自定义管道,可以从API检索文本内容,如下所示:
@Pipe({ name: 'apiText' })
export class ApiTextPipe implements PipeTransform {
constructor(private myApiService: MyApiService) {
}
transform(key: string): Observable<string> {
return this.myApiService.getText(key);
}
}
我必须像这样使用它:
<strong>{{'some-key' | apiText | async}}</strong>
但实际上,我将总是 想要组合apiText
和async
管道。我更愿意这样写:
<strong>{{'some-key' | apiTextAsync}}</strong>
我能以某种方式做到这一点,并通过组合两个管道使事情变得更干燥吗?
答案 0 :(得分:3)
几个评论者指出(正确地如此),这违反了SRP,并可能会损害可读性。但是,即使这会让我重新考虑是否想要,我仍然肯定想知道如何 如果需要的话。我找到了两个解决方案(再次在评论者的帮助下)。
组成(不推荐)
创建自己的内部AsyncPipe
并使用它。这是应该工作的基本设置:
@Pipe({ name: 'apiText', pure: false })
export class ApiTextPipe implements PipeTransform, OnDestroy {
private asyncPipe: AsyncPipe;
constructor(private myApiService: MyApiService, private injector: Injector) {
this.asyncPipe = new AsyncPipe(injector.get(ChangeDetectorRef));
}
ngOnDestroy() {
this.asyncPipe.ngOnDestroy();
}
transform(key: string): string {
return this.asyncPipe.transform(this.myApiService.getText(key));
}
}
除了上述缺点(评论者指出)之外,我还看到其他问题:
如果AsyncPipe发生更改,例如它开始实现OnInit
,然后我们自己的管道也需要更改。您可能会错过这一点。将管道的实现以这种方式耦合到AsyncPipe并不是很好。
我似乎无法注入AsyncPipe
,因为它依赖于特殊的ChangeDetectorRef
,所以我使用了this suggested approach直接从注入器询问。 (也许有更好的方法可以做到这一点,但我暂时不做进一步的挖掘……)
继承(不推荐)
您也可以尝试在自己的管道中extends AsyncPipe
,但是那条路线的代码更加笨拙,将您的管道与异步管道紧密耦合。我尝试这种方法时遇到了一些问题:
ChangeDetectorRef
才能传递到super(...)
通话transform
中AsyncPipe
方法的签名transform
变得非常复杂,因为它不再只需要一个字符串(请参见上一点)ngOnDestroy
方法加上我忘了的其他东西。我觉得代码很讨厌,甚至共享它似乎也不明智。
复制源(不推荐)
正如评论者之一所建议的,the source for AsyncPipe
是开放的。因此,您可以采用它并以此来构建自己的管道。
出于明显的原因,这不是一个明智的决定。
最重要的是,我现在对我自己的问题的回答(尽管我很高兴地证明另一个答案是错误的!)是,这不容易实现,最好的解决方案是不解决任何问题:坚持坚持模板中的管道。