Help us understand the problem. What is going on with this article?

初期表示処理でいっぱいapi呼んでformを作成しないといけない時のRxJSの書き方(最適化版)

この記事の概要

前回の記事の呼び方は適切でなかったので今回は下記の呼び方で実装します。

[1].
- [1-1]データA・Bを並行で取得
- [1-2]データD・E・Fを並行で取得
[2].データC取得
[3].その他非同期処理(form作成の事前準備)

上記[1]・[2]・[3]を並行で処理後、取得したデータでformを作成する

(前回の方法ではデータC取得処理とその他非同期処理も終わらなければデータD・E・F取得処理に進めない)

実装

ngOnInit() {
  // [1][2][3]を並行で処理
  forkJoin(
    // ここから[1]
    forkJoin(
      // ここから[1-1]。A・B取得処理を並行
      this.fetchA(),
      this.fetchB()
      // ここまで[1-1]
    ).pipe(
      // [1-2]処理後
      // ここから[1-2]
      flatMap(([dataA, dataB]) =>
        // D・E・F取得処理を並行。AとBの取得結果も後続の処理に返す
        forkJoin(
          of(dataA),
          of(dataB),
          this.fetchD(dataA),
          this.fetchE(dataB),
          this.fetchF(dataA, dataB)
        )
      )
      // ここまで[1-2]
    ),
    // ここまで[1]
    this.fetchC(), // [2]
    this.otherObservableFn() // [3]
  ).pipe(
  // [1][2][3]処理後
    /*
     * ※resの中は
     * [
     *   [dataA, dataB, dataD, dataE, dataF], // [1]
     *   dataC, // [2]
     *   otherFn // [3]
     *  ]
     * です
     */
  ).subscribe(res => {
    this.createForm(res);
    this.showScreen = true;
  });
}

ちょっとリファクタリング

[1]は関数分けた方が可読性が良いと思います
また、JSON形式で必要なデータのみcreateFormに渡すようにしてみます

ngOnInit() {
  forkJoin(
    this.fetchBaseData(),
    this.fetchC(),
    this.otherObservableFn()
  ).pipe(
    /*
     * resの中身:
     * [
     *   { dataA, dataB, dataD, dataE, dataF }
     *   , dataC
     *   , otherObservableFnの戻り
     * ]
     * ここからmapでdataCもJSON形式に組み込み、
     * otherObservableFnの戻りを除外して
     * フォームに必要なデータだけ後続に返すようにする。
     */
    map(res => Object.assign({}, { ...res[0] }, { dataC: res[1] })
    // res2の中身: { dataA, dataB, dataD, dataE, dataF, dataC }
  ).subscribe(res2 => {
    this.createForm(res2);
    this.showScreen = true;
  );
}

// 戻りの型はinterface定義した方が良いです。
private fetchBaseData(): Observable<{ dataA: AModel, dataB: BModel, dataD: DModel, dataE: EModel, dataF: FModel }> {
  return forkJoin(this.fetchA(), this.fetchB()).pipe(
    flatMap(([dataA, dataB]) =>
      forkJoin(
        of(dataA),
        of(dataB),
        this.fetchD(dataA),
        this.fetchE(dataB),
        this.fetchF(dataA, dataB)
      )
    ),
    // JSON型で返すようにする
    map(res => {
      return {
        dataA: res[0],
        dataB: res[1],
        dataD: res[2],
        dataE: res[3],
        dataF: res[4]
      };
    })
  );
}
pg_yamaton
Angular大好きおじさん 自称RxJSマスター フリーランス その他経歴・スキル: https://qiita.com/pg_yamaton/private/662add8109f08ed47d29
https://github.com/yamatoto
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away