我有一个可观察的myObservable
:
let myObservable = Observable.of(2000, 1000)
使用concatMap()
:TOTAL TIME = 3000 millis,产生原始订单。
myObservable.concatMap(v => Rx.Observable.of(v).delay(v))
// concatMap: 2000, concatMap: 1000
使用mergeMap()
:TOTAL TIME = 2000 millis,结果不是原始顺序。
myObservable.mergeMap(v => Rx.Observable.of(v).delay(v))
// mergeMap: 1000, mergeMap: 2000
我希望有一种方法可以像concatMap
一样以原始顺序获取结果,但是异步调用每个嵌套的observable而不是等待下一个嵌套的observable完成:
// --- The behavior that I want ---
myObservable.myCustomMap(v => Rx.Observable.of(v).delay(v))
// myCustomMap: 2000, myCustomMap: 1000
// TOTAL TIME = 2000 millis
有优雅的解决方案吗?
编辑:我正在寻找一种解决方案,如果源(myObservable
)是异步的,它也可以正常工作,不仅适用于这种特殊的同步情况。
答案 0 :(得分:1)
您应该使用forkJoin
同时触发所有可观察对象。
这是一个没有评论的例子:
const { Observable } = Rx;
const obs$ = Observable
.of(3000, 3000, 1000)
.map(x => Observable.of(x).delay(x));
const allObsWithDelay$ = obs$.toArray();
const result$ = allObsWithDelay$
.switchMap(arr => Observable.forkJoin(arr));
result$
.do(console.log)
.subscribe();
同样的解释:
const { Observable } = Rx;
// source observable, emitting simple values...
const obs$ = Observable
.of(3000, 3000, 1000)
// ... which are wrapped into a different observable and delayed
.map(x => Observable.of(x).delay(x));
// use a reduce to build an array containing all the observables
const allObsWithDelay$ = obs$.toArray();
const result$ = allObsWithDelay$
// when we receive the array with all the observable
// (so we get one event, with an array of multiple observables)
.switchMap(arr =>
// launch every observable into this array at the same time
Observable.forkJoin(arr)
);
// display the result
result$
.do(console.log)
.subscribe();
使用这些值:3000, 3000, 1000
整个过程需要3秒钟(当它们同时被触发时,它们的最大值)
工作Plunkr: https://plnkr.co/edit/IRgEhdjCmZSTc6hSaVeF?p=preview
修改1:感谢@PierreCitror指出toArray
优于scan
:)
答案 1 :(得分:1)
我会这样做:
myObservable
.mergeMap((val, i) => Observable.forkJoin(
Observable.of(i),
Observable.of(v).delay(v)
))
.scan((acc, ([i, result])) => {
acc[i] = result;
return acc;
}, {})
.filter(allResults => {
// Whatever goes here
Object.keys(allResults) // list indices of all finished responses
})
这将在单个对象中累积所有响应,其中每个响应都被分配了一个到达mergeMap
的索引。
然后在filter
中,您可以编写您想要的任何逻辑,以决定当前状态是否应该进一步传播(例如,您可以等到一定数量的响应到达或等等)。