Это хороший способ позвонить подписке внутри подписки?
this.service.service1().subscribe( res1 => {
this.service.service1().subscribe( res2 => {
this.service.service1().subscribe( res3 => {
this.funcA(res1, res2, res3);
});
});
});
Мне нужно передать три данных одной функции из трех разных API.
Хорошая практика подписаться внутри подписки?
Если нет, пожалуйста, предложите лучший способ.
Ответы
Ответ 1
Правильный способ состоит в том, чтобы составить различные наблюдаемые в некотором роде, а затем подписаться на общий поток - как вы их составите, будет зависеть от ваших точных требований.
Если вы можете сделать их все параллельно:
forkJoin(
this.service.service1(), this.service.service2(), this.service.service3()
).subscribe((res) => {
this.funcA(res[0], res[1], res[2]);
});
Если каждый из них зависит от результата предыдущего:
this.service.service1().pipe(
flatMap((res1) => this.service.service2(res1)),
flatMap((res2) => this.service.service3(res2))
).subscribe((res3) => {
// Do something with res3.
});
... и так далее. Существует множество разных операторов для составления наблюдаемых.
Ответ 2
Вы можете использовать forkJoin
для объединения Observables
в одно значение Observable
forkJoin(
this.service.service1(),
this.service.service1(),
this.service.service1()
).pipe(
map(([res1, res2, res3 ]) => {
this.funcA(res1, res2, res3);
})
Ответ 3
Если вызовы можно разрешить параллельно, вы можете использовать forkJoin, например:
joinedServiceCalls() {
return forkJoin(this.service1(), this.service2(), this.service3());
}
А затем подпишитесь на этот метод. https://www.learnrxjs.io/operators/combination/forkjoin.html
Ответ 4
Выглядит странно, я бы пошел так, потому что он выглядит чище:
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);
//...
}
РЕДАКТИРОВАТЬ
или сделать это параллельно
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
Вы можете использовать оператор zip RxJs, и тогда в этом случае вы будете использовать только одну подписку.
Затем вы можете вызвать свою функцию внутри этой подписки, потому что все результаты доступны.
Observable.zip(
this.service.service1(),
this.service.service1(),
this.service.service1()
).subscribe([res1, res2, res3]) {
this.funcA(res1, res2, res3);
}
Ответ 6
Как уже упоминалось, forkjoin - хорошее решение, но оно генерирует только завершенные вызовы. Если это значения, которые будут выдаваться многократно, используйте, я бы добавил, последний.