Это хороший способ позвонить подписке внутри подписки? - программирование
Подтвердить что ты не робот

Это хороший способ позвонить подписке внутри подписки?

this.service.service1().subscribe( res1 => {
  this.service.service1().subscribe( res2 => {
    this.service.service1().subscribe( res3 => {
      this.funcA(res1, res2, res3);
  });
  });
});

Мне нужно передать три данных одной функции из трех разных API.

Хорошая практика подписаться внутри подписки?

Если нет, пожалуйста, предложите лучший способ.

4b9b3361

Ответ 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 - хорошее решение, но оно генерирует только завершенные вызовы. Если это значения, которые будут выдаваться многократно, используйте, я бы добавил, последний.