RxJS 的一个很好的特性是您可以任意深度地嵌套流。因此,如果您可以构建一个丰富单个对象的流,那么您可以嵌套其中的 20 个来丰富整个数组。
因此,对于一个丰富的对象,将丰富的对象打印到控制台的流可能如下所示:
const oneObject = getObject();
forkJoin({
firstResult: this.myService.checkFirst(oneObject.id),
secondResult: this.myService.checkSecond(oneObject.id)
}).pipe(
map(({firstResult, secondResult}) => {
oneObject.first = firstResult;
oneObject.second = secondResult;
return oneObject;
})
).subscribe(
console.log
);
如果oneObject 本身是从可观察对象返回的,那么同样的事情会是什么样子?是一样的,只是现在我们将对象合并或切换到我们在上面创建的同一流中。
this.myService.getOneObject().pipe(
mergeMap(oneObject =>
forkJoin({
firstResult: this.myService.checkFirst(oneObject.id),
secondResult: this.myService.checkSecond(oneObject.id)
}).pipe(
map(({firstResult, secondResult}) => {
oneObject.first = firstResult;
oneObject.second = secondResult;
return oneObject;
})
)
)
).subscribe(
console.log
);
现在,还剩一步。为整个对象数组执行所有这些操作。为了实现这一点,我们需要一种方法来运行一组可观察对象。幸运的是,我们有 forkJoin - 我们用来同时运行 checkFirst 和 checkSecond 的运算符。它也可以将整个事物连接在一起。可能看起来像这样:
this.myService.getAll().pipe(
map(allRes =>
allRes.result.map(m =>
forkJoin({
first: this.myService.checkFirst(m.id),
second: this.myService.checkSecond(m.id)
}).pipe(
map(({first, second}) => {
m.first = first;
m.second = second;
return m;
})
)
)
),
// forkJoin our array of streams, so that your 40 service calls (20 for
// checkFirst and 20 for checkSecond) are all combined into a single stream.
mergeMap(mArr => forkJoin(mArr)),
).subscribe(resultArr => {
// resultArr is an aray of length 20, with objects enriched with a .first
// and a .second
// Lets log the result for he first object our array.
console.log(resultArr[0].first, resultArr[0].second)
});
这是我将map 和mergeMap 合并为一个mergeMap 的相同解决方案:
this.myService.getAll().pipe(
mergeMap(allRes =>
forkJoin(allRes.result.map(m =>
forkJoin({
first: this.myService.checkFirst(m.id),
second: this.myService.checkSecond(m.id)
}).pipe(
map(({first, second}) => {
m.first = first;
m.second = second;
return m;
})
)
))
)
).subscribe(console.log);
如果您不确定checkFirst 和checkSecond 是否完整,您可以使用zip 代替forkJoin,然后使用take(1) 或first() 取消订阅
this.myService.getAll().pipe(
mergeMap(allRes =>
forkJoin(allRes.result.map(m =>
zip(
this.myService.checkFirst(m.id),
this.myService.checkSecond(m.id)
).pipe(
first(),
map(([first, second]) => {
m.first = first;
m.second = second;
return m;
})
)
))
)
).subscribe(console.log);