【发布时间】:2020-02-17 17:39:14
【问题描述】:
我有一个由三个单独的搜索 API 提供服务的搜索框;您可以输入字符串或数字。字符串值非常简单,只返回找到的结果——可以是无或最多十个。对于数字,要么没有结果,要么只有一个结果,但必须进行第二次 GET 才能完成结果。输入的去抖时间为 300 毫秒,在输入三个字符之前不应开始搜索。
我的问题是,如果是数字,则进行了第二次 http 调用,但从未在结果集中实际使用过。 MapId 函数需要做其他事情——promise 显然不是可行的方法。
- 使用 forkJoin 代替 combineLatest 会更好吗?
- 我尝试过 flatMap,但无法将它与 forkJoin 结合使用。
- 我现在有点迷路了。结合 Angular 组件中的订阅等待,执行一次获取、检查结果并在需要时执行第二次获取应该不难。
Angular 组件文件:
searchTerm$ = new Subject<string>();
filterData$;
onFiltering(args: FilteringEventArgs): void {
this.searchTerm$.next(args.text);
}
setupSearchDebouncer(): void {
this.filterData$ = this.searchTerm$
.pipe(
debounceTime(300),
switchMap(s =>
iif(() => s.length >= 3,
this.searchService.find(s)
.pipe(
map((result) => {
return result.results
}),
),
of<Result[]>([])
))
);
this.filterData$.subscribe(r => {
this.filterArgs.updateData(r);
});
}
以及 RxJS 服务文件:
find(searchQuery: string) {
return combineLatest(
this.apiService1.search(searchQuery).pipe(),
this.apiService2.search(searchQuery).pipe(),
this.apiService3.search(searchQuery).pipe()
).pipe(
map(([stringResult, idResult1, idResult2]) => {
if (idResult1.length > 0 || idResult2.length > 0) {
return this.mapName(idResult1, idResult2);
}
else {
return this.mapId(stringResult);
}
})
);
}
mapId(stringResult): SearchResult {
// do some mapping
return result;
}
mapName(idResult1, idResult2): SearchResult {
const result = new SearchResult();
let id = undefined;
if (idResult1 && idResult1.length > 0) {
id = idResult1[0].Id;
}
else if (idResult2 && idResult2.length > 0) {
id = idResult2[0].Id;
}
this.apiService.fetchName(id).toPromise().then(succes => {
result.results = [{ name: succes[0].name, id: id }];
});
return result;
}
【问题讨论】:
-
那么第二个请求是
this.apiService.fetchName(id),您只想在某些条件下执行? -
是的,只有在 idResult1 或 idResult2 中有结果时才应使用 mapName(并导致第二次 http get)。 (修正了一个错字;混淆了 mapId 和 mapName,抱歉)。