问题
this.service.service1().subscribe( res1 => {
this.service.service1().subscribe( res2 => {
this.service.service1().subscribe( res3 => {
this.funcA(res1, res2, res3);
});
});
});
I need to pass three data to one function from three different API's.
Is it a good practice to subscribe inside a subscribe?
If not, Please suggest the best way.
回答1:
The correct way is to compose the various observables in some manner then subscribe to the overall flow - how you compose them will depend on your exact requirements.
If you can do them all in parallel:
forkJoin(
this.service.service1(), this.service.service2(), this.service.service3()
).subscribe((res) => {
this.funcA(res[0], res[1], res[2]);
});
If each depends on the result of the previous:
this.service.service1().pipe(
flatMap((res1) => this.service.service2(res1)),
flatMap((res2) => this.service.service3(res2))
).subscribe((res3) => {
// Do something with res3.
});
... and so on. There are many different operators to compose observables.
回答2:
You can use forkJoin
to combine the Observables
into a single value Observable
forkJoin(
this.service.service1(),
this.service.service1(),
this.service.service1()
).pipe(
map(([res1, res2, res3 ]) => {
this.funcA(res1, res2, res3);
})
回答3:
If the calls can be resolved in parallel you could use forkJoin, like this:
joinedServiceCalls() {
return forkJoin(this.service1(), this.service2(), this.service3());
}
And then subscribe to that method. https://www.learnrxjs.io/operators/combination/forkjoin.html
回答4:
Looks strange, I would go this way because it looks cleaner:
async myFunction () {
//...
const res1 = await this.service.service1().toPromise();
const res2 = await this.service.service2().toPromise();
const res3 = await this.service.service3().toPromise();
this.funcA(res1, res2, res3);
//...
}
EDIT
or to do it in parallel
async myFunction () {
//...
let res1;
let res2;
let res3;
[res1,res2,res3] = await Promise.all([this.service.service1().toPromise(),
this.service.service2().toPromise(),
this.service.service3().toPromise()]);
this.funcA(res1, res2, res3);
//...
}
回答5:
You can use the zip RxJs operator, and then in this case you will only use just one subscribe.
You can then call your function inside that subscribe because all the results are available.
Observable.zip(
this.service.service1(),
this.service.service1(),
this.service.service1()
).subscribe([res1, res2, res3]) {
this.funcA(res1, res2, res3);
}
回答6:
as mentioned, forkjoin is a good solution, but it emit completed calls only. If these are values that are going to be emitted repeatedly, use I would combineLatest.
来源:https://stackoverflow.com/questions/52317494/is-it-good-way-to-call-subscribe-inside-subscribe