0
votes

I have a problem when retrieving the results of two http async calls.

The first route is called /contracts and the second route is called /shipments Each contract is related to a shipment so it has a shipmentId property. I want to retrieve all the contracts and for each contract get his respective shipment from my REST server.

I tried calling both the getContracts() and getShipments() and then forEach contract to use find in my shipments[] (the result from getShipments() method) but sometimes the shipments call response returns after the contracts call response and so a cannot read property x of undefined error is returned.

I tried using also getShipmentById() but this doesn't assures me that all the time the shipment will be returned after the contract.

How can this be achieved using Angular / RxJS?

Here are relevant parts of my code:

  getContracts(): Observable<Contract[]> {
    return this.http.get<Contract[]>(this.contractsUrl)
      .pipe(
        retry(3),
        catchError(this.handleError('getContracts', []))
      );
  }

  getShipments(): Observable<Shipment[]> {
    return this.http.get<Shipment[]>(this.shipmentsUrl)
      .pipe(
        retry(3),
        catchError(this.handleError('getShipments', []))
      );
  }

  getShipmentById(id: string): Observable<Shipment | {}> {
    return this.http.get<Shipment>(`${this.shipmentsUrl}/${id}`)
      .pipe(
        retry(3),
        catchError(this.handleError('getShipmentById'))
      );
  }
1
Does endpoint /contracts return an id or value that needs to be used in /shipments? Or do you mean the /contracts and /shipments are called simultaneously, then a subsequent call happens to /shipments/:id after the previous ones completed? You may want to make a Stackblitz and using of or similar to demonstrate the flow and return data structures. - Alexander Staroselsky

1 Answers

0
votes

forkJoin did the trick.

Thank you for the answer, I didn't knew about this function. I'm posting here the code maybe it will help someone else having this problem:

  getContracts(): void {
    forkJoin(
      this.contractService.getContracts(),
      this.shipmentService.getShipments()
    )
      .subscribe(([contracts, shipments]) => {
        if (Array.isArray(contracts) && Array.isArray(shipments)) {
          this.contracts = contracts
            .map(contract => {
              contract.shipment = shipments.find(shipment => shipment.shipmentId === contract.shipmentId);
              return contract;
            });
        }

        console.log(contracts);
      });
  }