Reputation: 77
This is what I have:
ngOnInit() {
this._addServ.getDefaultAddress().subscribe((res)=>{
if(res.status){
//I need these next two functions to finish their async API requests
//before selectNormalDelivery is called
this.selectShippingAddress();
this.selectBillingAddress();
this.selectNormalDelivery();
}
})
}
I need selectShippingAddress
and selectBillingAddress
to finish their calls, and then for selectNormalDelivery
to be called. How can I accomplish this? I don't want to convert them into promises as they're called other times without needing to be chained. Is this something involving .then
?
This is the code for the functions:
selectShippingAddress(){
this.addressService.setShippingAddresses(this.cartService.shippingAddress.address_id).subscribe((res) => {
console.log('Set shipping address!')
console.log(res);
}, err => {
console.log('Failed to set shipping address')
console.log(err);
})
}
selectBillingAddress(){
this.addressService.setPaymentAddresses(this.cartService.billingAddress.address_id).subscribe((res) => {
console.log('Set billing address!')
console.log(res);
}, err => {
console.log('Failed to set billing address')
console.log(err);
})
}
If I try a .then
, I get the error Property 'then' does not exist on type 'void'.
, which makes sense as I'm not trying to return anything, I just need them to complete their calls for the API's sake.
Suggestions?
Upvotes: 0
Views: 841
Reputation: 31105
If I understand correctly, you need to listen to one observable (from getDefaultAddress()
), then process two other observables (this.addressService.setShippingAddresses()
and this.addressService.setPaymentAddresses()
) and after that call function selectNormalDelivery()
.
You could do so by using RxJS switchMap
, catchError
, tap
operators and forkJoin()
. Try the following
import { forkJoin, EMPTY } from 'rxjs';
import { tap, catchError, switchMap } from 'rxjs/operators';
ngOnInit() {
this._addServ.getDefaultAddress().pipe(
switchMap((res) => { // <-- map the observable from `getDefaultAddress()` to another observable
if(res.status) {
return forkJoin([ // <-- `forkJoin` emits only after the observables complete
this.selectShippingAddress(), this.selectBillingAddress()
])
}
})
).subscribe(response => {
this.selectNormalDelivery()
})
}
selectShippingAddress() {
return this.addressService.setShippingAddresses(this.cartService.shippingAddress.address_id).pipe(
tap((res) => { // <-- `tap` doesn't alter the response
console.log('Set shipping address!')
console.log(res);
}),
catchError((err) => { // <-- `catchError` must return an observable
console.log('Failed to set shipping address')
console.log(err);
return EMPTY;
}))
}
selectShippingAddress() {
return this.addressService.setPaymentAddresses(this.cartService.shippingAddress.address_id).pipe(
tap((res) => {
console.log('Set billing address!')
console.log(res);
}),
catchError((err) => {
console.log('Failed to set billing address')
console.log(err);
return EMPTY;
}))
}
Upvotes: 1
Reputation: 10969
ngOnInit() {
this._addServ.getDefaultAddress().subscribe((res)=>{
if(res.status){
//I need these next two functions to finish their async API requests
//before selectNormalDelivery is called
forkJoin([this.selectShippingAddress(),this.selectBillingAddress()].subscribe(() => {
this.selectNormalDelivery();
});
}
})
}
selectShippingAddress(){
return this.addressService.setShippingAddresses(this.cartService.shippingAddress.address_id).pipe(map((res) => {
console.log('Set shipping address!')
console.log(res);
}, err => {
console.log('Failed to set shipping address')
console.log(err);
}));
}
selectBillingAddress(){
return this.addressService.setPaymentAddresses(this.cartService.billingAddress.address_id).pipe(map((res) => {
console.log('Set billing address!')
console.log(res);
}, err => {
console.log('Failed to set billing address')
console.log(err);
}));
}
Upvotes: 0