Как вызывать одну асинхронную функцию за другой? - PullRequest
0 голосов
/ 29 мая 2020

Это то, что у меня есть:

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

Мне нужно selectShippingAddress и selectBillingAddress, чтобы завершить sh их звонки, а затем selectNormalDelivery для вызова. Как я могу сделать это sh? Я не хочу превращать их в обещания, как в других случаях, без необходимости связывания цепочек. Это что-то, связанное с .then?

Это код для функций:

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

Если я попробую .then, я получу ошибку Property 'then' does not exist on type 'void'., что имеет смысл поскольку я не пытаюсь ничего вернуть, мне просто нужно, чтобы они завершили свои вызовы ради API.

Предложения?

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Если я правильно понимаю, вам нужно прослушать один наблюдаемый (из getDefaultAddress()), затем обработать два других наблюдаемых (this.addressService.setShippingAddresses() и this.addressService.setPaymentAddresses()) и после этого вызвать функцию selectNormalDelivery().

Это можно сделать с помощью операторов Rx JS switchMap, catchError, tap и forkJoin(). Попробуйте следующее

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;
    }))
}
0 голосов
/ 29 мая 2020
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);
    }));
  }
...