[英]RxJS forkJoin piped observables
I need to make a number of calls to the server to save some data, and each subsequent call requires some data from the result of the previous call.我需要对服务器进行多次调用以保存一些数据,并且每次后续调用都需要来自上一次调用结果的一些数据。 Tried to use forkJoin, but the sequence of events does not makes sense (at least to me).
尝试使用 forkJoin,但事件顺序没有意义(至少对我而言)。 I figure the problem is with the.pipe() call where I'm trying to modify the input data for the next call.
我认为问题出在 .pipe() 调用上,我正在尝试修改下一次调用的输入数据。
So I have two questions:所以我有两个问题:
Here's some sample code, or StackBlitz .这是一些示例代码或StackBlitz 。
let data: { [key: string]: any } = {};
forkJoin(
this.saveFirst(data).pipe(
tap(_ => console.log('saveFirst pipe after')),
tap(result => data.id = result.id)
),
this.saveSecond(data).pipe(
tap(_ => console.log('saveSecond pipe after')),
tap(result => data.name = result.name)
),
).subscribe(result => console.log('done: data - ', JSON.stringify(data)));
...
private saveFirst(data: { [key: string]: any }): Observable<any> {
console.log('saveFirst: start');
console.log('saveFirst: data - ', JSON.stringify(data));
// replaced call to server with "of({ id: 1 })" for simplicity of example
return of({ id: 1 }).pipe(tap(_ => console.log('saveFirst: end')));
}
private saveSecond(data: { [key: string]: any }): Observable<any> {
console.log('saveSecond: start');
console.log('saveSecond: data - ', JSON.stringify(data));
// replaced call to server with "of({ name: 'test' })" for simplicity of example
return of({ name: 'test' }).pipe(tap(_ => console.log('saveSecond: end')));;
}
I was expecting the following output:我期待以下 output:
saveFirst: start
saveFirst: data - {}
saveFirst: end
saveFirst pipe after
saveSecond: start
saveSecond: data - {}
saveSecond: end
saveSecond pipe after
done: data - {"id":1,"name":"test"}
But instead got this:但是得到了这个:
saveFirst: start
saveFirst: data - {}
saveSecond: start
saveSecond: data - {}
saveFirst: end
saveFirst pipe after
saveSecond: end
saveSecond pipe after
done: data - {"id":1,"name":"test"}
You need to use mergeMap / switchMap in this case.在这种情况下,您需要使用mergeMap / switchMap 。
this.saveFirst(data).pipe(
tap(_ => this.actions.push('saveFirst pipe after')),
tap(result => data.id = result.id),
switchMap((res)=>{
return this.saveSecond(data).pipe(
tap(_ => this.actions.push('saveSecond pipe after')),
tap(result => data.name = result.name)
);
})).subscribe(result => this.actions.push('done: data - ' + JSON.stringify(data)));
The above code will produce the result you need.上面的代码会产生你需要的结果。 forkJoin is used when we want to issue multiple requests and only care about the final result.
当我们想要发出多个请求并且只关心最终结果时使用forkJoin 。
Forked Stackblitz .分叉的Stackblitz 。
If order of execution is important, you need to use concatMap instead of forkjoin如果执行顺序很重要,则需要使用 concatMap 而不是 forkjoin
this.saveFirst(data).concatMap(() => this.saveSecond(data)).subscribe()
https://www.learnrxjs.io/learn-rxjs/operators/transformation/concatmap which mentions using concatMap when order is important. https://www.learnrxjs.io/learn-rxjs/operators/transformation/concatmap提到在订单很重要时使用 concatMap。
I've been struggled with the same issue, the only solution I found is without piping the observables, but handle all responses after subscribing the forjoin.我一直在为同样的问题而苦苦挣扎,我找到的唯一解决方案是不使用管道传输 observables,而是在订阅 forjoin 后处理所有响应。
It will run both tasks in parallel , and not sequently like above solutions.它将并行运行这两个任务,而不是像上述解决方案那样依次运行。 I moved your handling from 'tap' to new handling methods, and called them once forkJoin subscription finished.
我将您的处理从“点击”转移到新的处理方法,并在 forkJoin 订阅完成后调用它们。
yourMethod()
{
let data: { [key: string]: any } = {};
forkJoin(
this.saveFirst(data),
this.saveSecond(data)
).subscribe(([res1, res2]) =>
{
this.handleSuccess_1(res1, data);
this.handleSuccess_2(res2, data);
console.log('done: data - ', JSON.stringify(data));
});
}
handleSuccess_1(res, data)
{
console.log('saveFirst pipe after');
data.id = res.id;
}
handleSuccess_2(res, data)
{
console.log('saveSecond pipe after');
data.name = res.name;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.