【发布时间】:2019-12-01 05:09:55
【问题描述】:
我开始精通 RxJS 运算符,但我仍然对其中一些有困难。在实现搜索组件时,我有以下代码:
searchResult$: Observable<LunrDoc []>;
searchResultLength$: Observable<number>;
ngAfterViewInit(): void {
// observable to produce an array of search hits
this.searchResult$ = fromEvent<Event>(this.searchInput.nativeElement, 'keyup').pipe(
debounceTime(1000),
switchMap(e => this.ss.search((e.target as HTMLTextAreaElement).value)),
share()
);
// observable to return the length of the array
this.searchResultLength$ = this.searchResult$.pipe(
map(sr => sr ? sr.length : 0),
share()
);
}
这在模板中是这样使用的:
<p *ngIf="(searchResultLength$ | async) > 0">
Total Documents: {{ (searchResultLength$ | async) | number }}
</p>
<p *ngFor="let doc of (searchResult$ | async)">
<span *ngIf="doc.path" [routerLink]="doc.path" style="color: darkblue; font-weight: bold; text-underline: darkblue; cursor: pointer">
{{ doc.title }}
</span>
{{ doc.content.substring(0, 400) }}
</p>
当searchResult$ observable 发出一个非空数组时会发生什么,第一个段落元素中的呈现结果为“Total Documents:”,后面没有数字。 *ngFor 修饰的段落完全按预期工作。
我相信的原因是第二个async 管道在最后一个值发出后被激活并订阅了共享的 observable。所以它永远不会得到“下一个”调用。
是否可以使用 RxJS 运算符代替 share 来解决这种情况?还是我错过了什么?
【问题讨论】:
-
您的解释听起来很有道理,您可以尝试改用
shareReplay(1)。 -
我完全看不出
share的理由,你真的需要吗? -
共享对可观察对象进行多播,这样就不会针对每个订阅单独命中搜索 API。不过,可观察到的长度上的份额不是必需的。该代码还可以使用 ngIf 的“as”特性来避免一些重复。