假设我有一个称为“ todoList $”的观察对象。使用“异步”运算符,我可以自动对其进行订阅/取消订阅。下面的代码中的问题是,同一可观察对象有两个相同的订阅:
<ng-container *ngIf="(todoList$ | async).length > 0>
<div *ngFor="let todo of todoList$ | async">
...
这不是很干,因此,我们为可以更有效处理的预订分配内存。
由于ngIf条件中的语法,我不相信我可以使用'as'关键字为可观察的输出创建模板变量。相反,当我从组件文件中使用RxJs的“ share”运算符时,有效的方法是:
todoList$ = this.store.select(todoList).pipe(tap(x => {console.log('testing')}), share());
//testing
没有共享运算符,“测试”打印两次。这使我相信share()运算符可以解决此问题。如果确实如此,则不完全清楚为什么/如何做?由于这可能是普遍存在的问题/代码异味,因此处理同一模板中相同的多个订阅的最佳方法是什么?
我承认在StackOverflow上有一些类似的问题。但是没有人能给我确切的信息。
通常,我shareReplay({ refCount: true, bufferSize: 1 })
在Observable
模板内部每个末尾使用运算符。我还将其添加到基本可观察对象中,该基本可观察对象用于分支其他可观察对象,然后将其用于模板中。这将确保订阅在每个订阅者之间共享,并且通过使用,shareReplay
您还可以使用在组件内部获取最后发出的结果take(1)
。
的原因{ refCount: true, bufferSize: 1 }
是,如果仅使用shareReplay(1)
它,则可能导致订阅泄漏,无论您是否使用async
管道。
回到您的示例,提供的答案还Michael D
不错,并且这样做是有意义的。但是,它确实需要模板中的一些逻辑,我个人对此并不满意。
因此,只要您使用shareReplay
,async
在模板中使用多个调用实际上就没有任何弊端,您甚至可以通过在组件中定义它们来使它们在整个模板中具有描述性和可重用性:
export class TodoComponent {
readonly todoList$ = this.store.select(todoList).pipe(
shareReplay({ refCount: true, bufferSize: 1 })
);
readonly hasTodos$ = this.todoList$.pipe(
map((todos) => todos?.length > 0),
shareReplay({ refCount: true, bufferSize: 1 })
);
}
然后,您可以使模板保持描述性:
<ng-container *ngIf="hasTodos$ | async>
<div *ngFor="let todo of todoList$ | async">
<!-- -->
不要忘记你的trackBy
!
如果您不喜欢重复代码,甚至可以创建自定义运算符,然后使用它:
export function shareRef<T>() {
return (source: Observable<T>) => source.pipe(
shareReplay({ refCount: true, bufferSize: 1 })
);
}
哪个将您的观察结果更改为:
readonly todoList$ = this.store.select(todoList).pipe(
shareRef()
);
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句