想找出答案,我可以等待递归forkJoin中所有的http调用。如何等待forkJoin中的所有http调用并接收最终结果?
目前,我有如下所示
public myMethod(urls: string[]) {
...
return forkJoin(observables)
.pipe(map(() => {
if (json.urls !== 0) {
return this.myMethod(json.urls);
}
}), catchError((err) => {
console.log(err);
return of(null);
})
);
}
And then I subscribe ...
public mainMehtod(){
return this.myMethod([json]).pipe(map(() => {
...some stuff here. But I need here the final result from the finished recursion
}));
编辑
我找到的解决方案是,收集递归中的所有可观测值,然后调用forkjoin。
发布于 2020-04-27 17:19:35
expand
是去这里的好方法。很难用所提供的代码使其精确,但看起来如下所示:
private _myMethod(urls: string[]) {
...
return forkJoin(observables).pipe(
catchError(err => {
console.log(err)
return of(null)
})
)
}
public myMethod(urls: string[]) {
return this._myMethod(urls).pipe(
// expand will feed the value of outter observable to start, and then call this function recursively with the result of subsequent calls inside expand
expand(json => {
if (json.urls.length) {
// expand calls itself recursively
return this._myMethod(json.urls);
}
return EMPTY; // break
}),
// expand emits outter result and then results of recursion one by one. how you collect this is up to you
// reduce is an option to collect all values in an array like this (like a forkJoin of your forkJoins)
// reduce((acc, val) => acc.concat([val]), [])
// last is an option if you only want the last recursive call (or first if none from recursion)
// last()
// or omit these entirely if you want the results one by one.
)
}
发布于 2020-04-27 17:06:12
有一个expand
操作符,可以解决你的问题。
下面是您应该如何使用它:
import { fromEvent, of, forkJoin, EMPTY } from 'rxjs';
import { expand, delay, map, reduce, last } from 'rxjs/operators';
const DATABASE: Element[] = [
{id:'one', childId: 'three'},
{id:'two', childId: 'four'},
{id:'three', childId: 'five'},
{id:'four', childId: 'six'},
{id:'five', childId: null},
{id:'six', childId: null}
];
mainMethod(['one', 'two']).subscribe(value => {
console.log(value.map(e => e.id));
})
function mainMethod(ids: string[]) {
return forkJoin(ids.map(id => getElementById(id))).pipe(
expand(values => {
if (values.some(el => el.childId)) {
return forkJoin(values
.filter(v => v.childId)
.map(el => getElementById(el.childId))
)
}
return EMPTY;
}),
last() // use this if you want only last emission. Be careful, last throws an error, if no value is passed
// reduce((acc, values) => acc.concat(values), []) // use this if you want everything
)
}
function getElementById(id: string) {
return of(DATABASE.find(el => el.id === id)).pipe(
delay(1000)
)
}
interface Element {id: string, childId: string | null}
https://stackoverflow.com/questions/61462476
复制相似问题