如何从Observable<Thing[]>中获取Observable<Thing>[]类型数组
实现方案说明
可以实现该转换,核心前提是转换逻辑必须在Observable<Thing[]> emit 出数组值之后执行,无法同步直接生成目标数组,具体实现参考如下:
基础静态转换方案
适用于源仅 emit 一次数组、子Observable不需要跟随源更新的场景:
import { Observable, map } from 'rxjs'; // 声明类型示例 interface Thing { // 你的Thing类型定义 id: number; name: string; } // 源Observable示例 const source$: Observable<Thing[]> = yourSourceObservable; // 转换为 Observable<Observable<Thing>[]> 类型 const higherOrder$ = source$.pipe( map((thingArr: Thing[]) => { // 遍历数组每项,单独封装为仅 emit 对应值的Observable return thingArr.map(thing => new Observable<Thing>(sub => { sub.next(thing); sub.complete(); })) }) ); // 订阅后即可拿到目标类型数组 higherOrder$.subscribe((targetArr: Observable<Thing>[]) => { // targetArr 就是你需要的 Observable<Thing>[] 类型 // 可单独订阅数组内的每个Observable targetArr.forEach(item$ => item$.subscribe(val => console.log(val))) })
动态同步转换方案
适用于源会多次 emit 新数组,需要子Observable同步对应位置最新值的场景:
import { Observable, BehaviorSubject } from 'rxjs'; const source$: Observable<Thing[]> = yourSourceObservable; const targetArr: Observable<Thing>[] = []; // 缓存对应位置的Subject实例用于更新值 const subjectStore: BehaviorSubject<Thing>[] = []; source$.subscribe(thingArr => { thingArr.forEach((item, index) => { if (!subjectStore[index]) { // 首次生成对应位置的Subject和Observable const sub = new BehaviorSubject<Thing>(item); subjectStore[index] = sub; targetArr[index] = sub.asObservable(); } else { // 已有对应实例,更新值即可 subjectStore[index].next(item); } }) // 可选:如果源数组长度变短,销毁多余的Subject避免内存泄漏 if (subjectStore.length > thingArr.length) { subjectStore.splice(thingArr.length).forEach(sub => sub.complete()); targetArr.splice(thingArr.length); } })
注意事项
- 目标数组的长度完全由源Observable emit的数组长度决定,源未返回结果时无法提前创建对应数量的子Observable
- 如果源emit的数组元素顺序会变化,需要额外加唯一标识匹配对应子Observable,不能直接按索引匹配
内容的提问来源于stack exchange,提问作者arcrub
相关产品推荐
相关产品推荐

