RxJS 6:将Observable<对象数组>转为Observable<单个对象>
解决方案:将发射数组的Observable转为逐个发射元素的Observable
你需要用到RxJS里的管道操作符来“展开”数组,让Observable逐个发射数组里的每个对象,常用的方案有两种:
方案一:使用concatMap/mergeMap + from()
of()会把整个数组作为单个值发射,而from()可以把数组转换成逐个发射元素的Observable。配合concatMap(保证顺序)或mergeMap(不严格要求顺序时使用),就能把原Observable的数组值拆分成单个对象发射。
修改后的代码如下:
import { of, from } from 'rxjs'; import { tap, concatMap } from 'rxjs/operators'; const obs$ = of([ { opponent: 'Walton', team: 'varsity', gametime: new Date() }, { opponent: 'Scott', team: 'varsity', gametime: new Date() }, { opponent: 'Dixie', team: 'varsity', gametime: new Date() }, { opponent: 'Highlands', team: 'freshmen', gametime: new Date() } ]) .pipe( concatMap(arr => from(arr)), // 将数组转为逐个发射元素的Observable tap(console.log) ); obs$.subscribe(a => console.log('订阅接收:', a));
简单解释:
concatMap会订阅from(arr)返回的Observable,按顺序发射数组里的每个对象- 如果你的场景不关心元素发射顺序,换成
mergeMap效果完全一致(同步数组场景下两者无差异)
方案二:使用mergeAll()/concatAll()
这是更简洁的写法,mergeAll()(或concatAll())可以直接展开“高阶Observable”——这里原Observable发射的数组会被自动识别为可展开的数据源,直接拆分成单个元素发射:
import { of } from 'rxjs'; import { tap, mergeAll } from 'rxjs/operators'; const obs$ = of([ { opponent: 'Walton', team: 'varsity', gametime: new Date() }, { opponent: 'Scott', team: 'varsity', gametime: new Date() }, { opponent: 'Dixie', team: 'varsity', gametime: new Date() }, { opponent: 'Highlands', team: 'freshmen', gametime: new Date() } ]) .pipe( mergeAll(), // 直接展开数组为单个元素 tap(console.log) ); obs$.subscribe(a => console.log('订阅接收:', a));
两种方案都能让obs$的行为和obs2$完全一致:每次订阅时逐个发射每个对象,而不是一次性发射整个数组。
内容的提问来源于stack exchange,提问作者user1247395
相关产品推荐
相关产品推荐

