web-dev-qa-db-ja.com

サブスクライブ内でサブスクライブを呼び出すのは良い方法ですか?

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

3つの異なるAPIから1つの関数に3つのデータを渡す必要があります。

サブスクライブ内でサブスクライブするのは良い習慣ですか?

そうでない場合は、最善の方法を提案してください。

16

正しい方法は、さまざまなオブザーバブルを何らかの方法で構成し、全体のフローをサブスクライブすることです。それらをどのように構成するかは、厳密な要件によって異なります。

すべてを並行して実行できる場合:

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.
});

... 等々。オブザーバブルを作成するには、さまざまな演算子があります。

21
Mark Hughes

forkJoinを使用して、Observablesを単一の値Observableに結合できます。

forkJoin(
    this.service.service1(),
    this.service.service1(),
    this.service.service1()
  ).pipe(
    map(([res1, res2, res3 ]) => {
      this.funcA(res1, res2, res3);
    })
3
Antoine V

呼び出しを並行して解決できる場合は、次のようにforkJoinを使用できます。

joinedServiceCalls() {
   return forkJoin(this.service1(), this.service2(), this.service3());
}

そして、そのメソッドにサブスクライブします。 https://www.learnrxjs.io/operators/combination/forkjoin.html

2
Diego Pedro

Zip RxJs operator を使用できます。この場合、1つのサブスクライブのみを使用します。

すべての結果が利用できるため、そのサブスクライブ内で関数を呼び出すことができます。

Observable.Zip(
  this.service.service1(),
  this.service.service1(),
  this.service.service1()
).subscribe([res1, res2, res3]) {
  this.funcA(res1, res2, res3);
}
0
HDJEMAI

前述のように、forkjoinは優れたソリューションですが、完了した呼び出しのみを出力します。これらが繰り返し出力される値である場合、Latestを結合します。

0
user856510

奇妙に見える、それはきれいに見えるので、私はこのように行くだろう:

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);
//...

}
0
hjbello