如何将Observable<string>[]转换为Observable<string[]>(RxJS实操问题)
实现方案
你可以通过 concat + toArray 操作符实现严格顺序执行、最终一次性返回完整数组的需求,代码如下:
import { of, concat } from 'rxjs'; import { map, concatMap, toArray } from 'rxjs/operators'; const response$ = of({results: [1, 2, 3]}); response$.pipe( map((response) => { return response.results.map((id) => { return of(id.toString()); }) }), // 按顺序执行所有Observable,执行完成后收集所有结果为数组 concatMap((stringObservables) => concat(...stringObservables).pipe(toArray())) ) .subscribe((response: string[]) => { console.log(response); // 仅触发一次,输出 ["1", "2", "3"] })
如果你的转换逻辑允许并行执行,不需要严格的执行顺序(最终结果顺序仍和原数组一致),可以用forkJoin简化实现,性能更高:
import { of, forkJoin } from 'rxjs'; import { map, concatMap } from 'rxjs/operators'; const response$ = of({results: [1, 2, 3]}); response$.pipe( map((response) => { return response.results.map((id) => { return of(id.toString()); }) }), // 等待所有Observable执行完成后,按输入顺序返回结果数组 concatMap((stringObservables) => forkJoin(stringObservables)) ) .subscribe((response: string[]) => { console.log(response); // 仅触发一次,输出 ["1", "2", "3"] })
原代码问题说明
你之前的写法中,concatMap直接返回Observable数组时,会将数组内的每个Observable逐个流出,再经过concatAll打平后每次返回单个字符串,因此会触发三次订阅回调。加上toArray操作符后,会等待上游所有值都流出后,一次性收集为数组返回,就只会触发一次订阅。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

