Home > Back-end >  wait for API call or subscription to finish/return before calling other subscriptions (await)
wait for API call or subscription to finish/return before calling other subscriptions (await)

Time:04-21

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

}

CodePudding user response:

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

CodePudding user response:

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);
}
  • Related