需要其他 observable 的結果作為其他 observable 的參數

請教大家一個類似資料庫 join 的問題

情境如下:
通過 API_1 呼叫後端傳送一份工作清單 (work order),裡面記錄了一些工作內容以及相關資訊,像是截止日期承辦員工 ID 等等。同時有另一個 API_2,可以將員工 ID 作為參數傳入,API_2 會傳出該員工的相關資料 (員工姓名等等)。

現在我想要將全部工作以及各自負責的員工呈現在頁面上,要如何利用 API_1 得到全部有業務的員工 ID,再利用這些 ID 傳入 API_2 ?

下面是我的 code,好像沒有成功讓 API_2 等待 API_1 的資料

this.dataService.getWorkOrders() 是 API_1 的資料,回傳 Observable<IWorkOrder[]>

this.dataService.getWorkers(workerId) 是 API_2 的資料,需傳入參數 workerId,回傳 Observable<IWorker>

ts 檔案

import { merge } from 'rxjs';
import { concatMap } from 'rxjs/operators';

  total = [];
  setWorkers(): void {
    let dependencyOrder = this.dataService.getWorkOrders().pipe(concatMap(workOrders => {
      // 收集全部的 workerId
      let workerIdSet = new Set<number>();
      for (let workOrder of workOrders) {
        workerIdSet.add(workOrder.workerId);
      }

      // 將 Set 裡面的不重複 workerId 取出來合併, 不關心先取哪一個員工
      let workerIds = [];
      for (let workerId of workerIdSet) {
        workerIds.push(this.dataService.getWorkers(workerId));
      }

      return merge(...workerIds);
    }));

    dependencyOrder.subscribe({
        next: worker => {
          // 之後出來的都是 IWorker, 將他們的值 (員工姓名等等) 放到 total 中 id 相對應的部分來合併
          if (worker instanceOf IWorker) {
            let id = worker.id;
            let work = this.total.find(element => element.workerId === id);

            for (let prop in worker) {
              // 跳過 worker id
              if (prop !== id) {
                work[prop] = worker[prop];
              }
            }
          }
          // 第一個出來 IWorkOrder[], 將他設為 total, 之後頁面呈現 total 裡面的元素
          else {
            this.total = worker;
          }
        },
        error: err => this.errorMessage = err
    });
  }

template

<app-workOrder-item *ngFor="let element of total" [element]="element"></app-workOrder-item>

看起來只要稍微調整一下應該就可以跑了

     return forkJoin(Array.from(workerIdSet).map(workerId => this.dataService.getWorkers(workerId)));
1個讚

感謝您的回答,我將最後修正好的程式碼貼在這邊做個記錄

import { forkJoin } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';

  total = [];
  setWorkOrderLists(): void {
    let dependencyOrder = this.dataService.getWorkOrders().pipe(concatMap(workOrders => {
      this.total = workOrders;

      // 收集全部的 workerId
      let workerIdSet = new Set<number>();
      for (let workOrder of workOrders) {
        workerIdSet.add(workOrder.workerId);
      }

      // 將 Set 裡面的不重複 workerId 取出來合併, 不關心先取哪一個員工
      return forkJoin(Array.from(workerIdSet).map(workerId => this.dataService.getWorkers(workerId)));
    }));

    dependencyOrder.subscribe({
      next: (workers: IWorker[]) => {
        // 之後出來的都是 IWorker, 將他們的值 (員工姓名等等) 放到 total 中 id 相對應的部分來合併
        for (let worker of workers) {
          let id = worker.id;
          let works = this.total.filter(element => element.workerId === id);

          for (let work of works) {
            for (let prop in worker) {
              switch (prop) {
                case "id":
                  break;
                default:
                  work[prop] = worker[prop];
              }
            }
          }
        }
      },
      error: err => this.errorMessage = err
    });
  }