Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wait for API call or subscription to finish/return before calling other subscriptions (await)

I am getting a bunch of failed API calls in the network tab in chrome. This is because I can see on the waterfall that my "create customer" subscription hasn't finished its execution yet, then "create address" and "create contact phone number" both run and don't wait for it to finish.

I have looked for answers using the await....toPromise() function, but that is now deprecated and doesn't work in my scenario.

How would I implement this in newer versions of rxjs/angular?

// API call for create customer
this.userService.createCustomer(customer).subscribe({
  next: (customerResult: Customer) => {
    const createContactAddress =
      customerAddress !== undefined
        ? this.userService.createContactAddress(
            customerResult.partyNumber,
            customerAddress.toJson()
          )
        : of(undefined);
    const createContactEmail =
      email !== undefined
        ? this.userService.createContactPhoneEmail(
            customerResult.partyNumber,
            email
          )
        : of(undefined);
    const createContactPhoneNumber =
      phone !== undefined
        ? this.userService.createContactPhoneEmail(
            customerResult.partyNumber,
            phone
          )
        : of(undefined);

    createContactAddress
      .pipe(combineLatestWith(createContactEmail, createContactPhoneNumber))
      .subscribe({
        next: () => {
          this.isSaving = false;
          this.modalSaved.emit(customerResult);
        },
        error: () => {
          this.isSaving = false;
          this.closeModal();
        }
      });
  },
  error: () => {
    this.isSaving = false;
    this.closeModal();
  }
});

}

like image 880
nugh Avatar asked Jan 26 '26 09:01

nugh


2 Answers

You can use switchMap/mergeMap to execute the logic in subscribe instead of nested subscribe

// API call for create customer
this.userService
  .createCustomer(customer)
  .pipe(
    switchMap((customerResult: Customer) => {
      const createContactAddress =
        customerAddress !== undefined
          ? this.userService.createContactAddress(
              customerResult.partyNumber,
              customerAddress.toJson()
            )
          : of(undefined);
      const createContactEmail =
        email !== undefined
          ? this.userService.createContactPhoneEmail(
              customerResult.partyNumber,
              email
            )
          : of(undefined);
      const createContactPhoneNumber =
        phone !== undefined
          ? this.userService.createContactPhoneEmail(
              customerResult.partyNumber,
              phone
            )
          : of(undefined);

      return createContactAddress.pipe(
        combineLatestWith(createContactEmail, createContactPhoneNumber)
      );
    })
  )
  .subscribe({
    next: () => {
      this.isSaving = false;
      this.modalSaved.emit(customerResult);
    },
    error: () => {
      this.isSaving = false;
      this.closeModal();
    }
  });
like image 149
Fan Cheung Avatar answered Jan 28 '26 23:01

Fan Cheung


What I understood is,

  1. you want to call this.userService.createCustomer
  2. After completion of [1] you want to perform these three createContactAddress, createContactEmail, createContactPhoneNumber
  3. After completion of [1] and [2] you want to complete the stream.

On basis of my understanding I am providing my solution

this.userService
  .createCustomer(customer)
  .pipe(
    switchMap((customerResult: Customer) =>
      forkJoin([
        this.createContactAddress(customerAddress, customerResult),
        this.createContactEmail(email, customerResult),
        this.createContactPhoneNumber(phone, customerResult),
      ]).pipe(map((result) => [customerResult, ...result]))
    ),
    catchError((err) => {
      this.isSaving = false;
      this.closeModal();
    })
  )
  .subscribe({
    next: (customerResult, addressResult, emailResult, phoneResult) => {
      this.isSaving = false;
      this.modalSaved.emit(customerResult);
    },
    error: () => {
      this.isSaving = false;
      this.closeModal();
    },
  });


createContactAddress(customerAddress, customerResult): Observable<any> {
  return customerAddress !== undefined
    ? this.userService.createContactAddress(
        customerResult.partyNumber,
        customerAddress.toJson()
      )
    : of(undefined);
}

createContactEmail(email, customerResult): Observable<any> {
  return email !== undefined
    ? this.userService.createContactPhoneEmail(
        customerResult.partyNumber,
        email
      )
    : of(undefined);
}

createContactPhoneNumber(phone, customerResult): Observable<any> {
  return phone !== undefined
    ? this.userService.createContactPhoneEmail(
        customerResult.partyNumber,
        phone
      )
    : of(undefined);
}
like image 44
Saptarsi Avatar answered Jan 29 '26 00:01

Saptarsi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!