javascript - 从 RXJS observable 获取中间数据的最佳方式
问题描述
我想调用第一个服务来查询一些数据(返回一个结果数组),然后再次调用第二个服务来为每个结果获取更多数据。每次服务调用的结果应合并并返回并显示在一个列表中。我想我理解那部分是如何工作的。
我不太确定的部分是要求能够在可用时立即显示第一次服务调用的结果。UI 应该在数据可用之前显示来自第二个服务调用的字段的加载指示符。
我唯一能想到的是在第一次服务调用和第二次服务调用之后添加“tap”rxjs 操作符,它会在新主题上发出事件,并且 UI 可以监听 _documents$ 主题以在第一次调用后显示数据,并在第二次调用后显示组合数据。
是否有处理这种情况的最佳实践?我是否错过了另一种模式或 rxjs 运算符,这会使这更简单?
_documents$: BehaviorSubject<DocumentSearchSomething[]> = new BehaviorSubject([]);
private documentSearchQuery$ = new Subject<string>();
constructor(private store: Store, private http: HttpClient) {
this.documentSearchQuery$.pipe(
switchMap((query) => {
return this.http.get<any[]>(`https://my_api.com/service_1?q=${encodeURIComponent(query)}`)
.pipe(
tap(service_1_results => this._documents$.next(service_1_results)),
switchMap(service_1_results => {
// make call to service 2 to get more data for each result, pass in id of every result
return this.http.post<any[]>(`https://my_api.com/service_2`, {
ids: service_1_results.map(r => r.id)
}).pipe(
map(service_2_results => {
// combine service_1_results with service_2_results
const combined = service_1_results.map(r1 => {
const r2 = service_2_results.find(c => c.id === r1.id);
return {...r1, ...r2};
});
return combined;
}),
tap(combined_results => this._documents$.next(combined_results))
);
})
);
}),
).subscribe();
}
解决方案
是的,您可以使用一个运算符来简化此操作。由于此管道设置了一个内部 observable(导致发出组合值),您可以使用startWith()
它立即从内部 observable 发出服务一的值。
_documents$: Observable<DocumentSearchSomething[]>;
private documentSearchQuery = new Subject<string>();
constructor(private store: Store, private http: HttpClient) {
this._documents$ = this.documentSearchQuery.pipe(
switchMap(query => this.http.get<any[]>(`https://my_api.com/service_1?q=${encodeURIComponent(query)}`)),
switchMap(serviceOne => this.HTMLOutputElement.post<any[]>(`https://my_api.com/service_2`, {
ids: serviceOne.map(r => r.id)
}).pipe(
map(serviceTwo => serviceOne.map(r1 => {
const r2 = serviceTwo.find(c => c.id === r1.id);
return { ...r1, ...r2 };
})),
startWith(serviceOne)
))
);
}
推荐阅读
- php - 我不能在数组中输入一个值?
- javascript - 样式不适用于注入 iframe 的角度组件
- objective-c - MKMapview 如何检查(探测)地图是否已加载?
- java - 如何检查我的数组中是否包含有空格的单词?
- django - request.POST.has_key(*...*) 中包含哪些键?
- javascript - 什么是正确的一个数组/对象或组合
- c - 如何创建一个只有结构的矩阵,然后为存储在矩阵中的每个数据创建一个线程?
- timer - 飞镖计时器似乎没有触发
- c# - 在 ASP .NET Core Web 服务器上备份 SQLite .db 文件
- html - 与 HTML 工具栏的高级搜索交互