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,
- you want to call
this.userService.createCustomer
- After completion of [1] you want to perform these three
createContactAddress
,createContactEmail
,createContactPhoneNumber
- 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);
}