Angular 7-如何一个接一个地调用API

时间:2019-03-10 07:20:00

标签: angular typescript api asynchronous

在加载第一个API时,我需要获取并将其传递给第二个API以获得详细信息。随着我目前的代码变量变得不确定。这是我的代码:

app.ts

export class DailyEndorsementComponent implements OnInit {

  public selectedShop: string;
  shop: string[];
  shopData: ShopData;


  constructor(private endorsementService: EndorsementService) {}

  ngOnInit() {
    this.getDates();
    this.loadShopList();
  }

  setPayload() {
    return {
      'startDate': this.fromDate,
      'endDate': this.toDate,
      'settlementBank': this.selectedShop,
    }
  }

  getDates(range: any) {
    this.fromDate = this.datePipe.transform(range.fromDate, 'yyyy-MM-dd');
    this.toDate = this.datePipe.transform(range.toDate, 'yyyy-MM-dd');
    this.loadMerchantDailyEndorsement();
  }

  loadShopList() {
    this.endorsementService.shopList()
      .subscribe(response => {
        this.shop = response;
        this.selectedShop = this.banks[0];
      })
  }

  loadMerchantDailyEndorsement() {
      this.endorsementService.getMerchantEndorsement(this.setPayload())
        .subscribe((response: EndorsementResponseInterface) => {
            this.shopData = response;
          }

        }

app.service.ts

export class EndorsementService extends RestService {

  private BASE_URL_MERCHANT: string = '/settlement/merchant/settlement';
  private BASE_URL_CUSTOMER: string = '/settlement/customer/settlement';

  private headers = new HttpHeaders({
    'Content-Type': 'application/json',
    'Authorization': localStorage.getItem('token')
  });

  constructor(protected httpClient: HttpClient,
    protected injector: Injector,
    protected snackBar: MatSnackBar) {
    super(injector);
  }

  getMerchantEndorsement(body: any): Observable < EndorsementResponseInterface > {
    return this.post < EndorsementResponseInterface >
      (this.getFullUrl(`${this.BASE_URL_MERCHANT}/daily/get`), body, {
        headers: this.headers
      });
  }

  shopList(): Observable < string[] > {
    return this.get < string[] >
      (this.getFullUrl(`/settlement/settlementbanks`), {
        headers: this.headers
      });
  }

}

我需要从 loadShopList()获取价值,然后调用并将其传递给loadMerchantDailyEndorsement()。请让我知道是否错过了任何事情。

3 个答案:

答案 0 :(得分:1)

为此,您需要将可观察的对象放平。

目标应具有1个可观察值(此处为this.endorsementService.shopList),它将与另一个可观察值(此处为mergeMapthis.endorsementService.getMerchantEndorsement

这意味着在shopList可见的任何时间都会在流上发射新数据:

  • 您将基于getMerchantEndorsement的当前值创建新的可观察的shopList
  • 将实际的shopList转换为getMerchantEndorsement流。

我创建了一个虚拟演示来演示:

// Simple observable to emulate selected shop from list.
const shopDetail$ = of({
  shop: {
    id: 1,
    name: 'My little poney Inc'
  }
}).pipe(delay(100)); // Delay is added to emulate api call delay. is optional

// Factory for remote data : simple function which emulate http request.
// Base on current id parameter, will return observable of marchandize detail.
const getMarchandizeDetail$ = (id: number) => {
  const dummyDb = { 
    '1': {marchandize : ['poney 1', 'poney 2', 'poney 3']},
    '2': {marchandize : ['element 1', 'element 2', 'element 3']},
  };

  return of(dummyDb[id]);
};

// When current shop change...
shopDetail$.pipe(mergeMap(
  info => {
    // We subscribe to http call : getMarchandizeDetail base on the current shop id.
    return getMarchandizeDetail$(info.shop.id)
  }
)).subscribe(console.log);

live demo

答案 1 :(得分:0)

您可以通过几种不同的方式来完成此任务,但是我相信您应该利用Promises。

export class DailyEndorsementComponent implements OnInit {

  public selectedShop: string;
  shop: string[];
  shopData: ShopData;

  constructor(private endorsementService: EndorsementService) {}

  ngOnInit() {
    this.loadShopList().then(() => {
      this.getDates();
    });
  }

  setPayload() {
    return {
      'startDate': this.fromDate,
      'endDate': this.toDate,
      'settlementBank': this.selectedShop,
    }
  }

  getDates(range: any) {
    this.fromDate = this.datePipe.transform(range.fromDate, 'yyyy-MM-dd');
    this.toDate = this.datePipe.transform(range.toDate, 'yyyy-MM-dd');
    this.loadMerchantDailyEndorsement();
  }

  loadShopList() {
    return new Promise((resolve) => {
        this.endorsementService.shopList()
          .subscribe(response => {
            this.shop = response;
            this.selectedShop = this.banks[0];
            resolve();
          });
    });
  }

  loadMerchantDailyEndorsement() {
      this.endorsementService.getMerchantEndorsement(this.setPayload())
        .subscribe((response: EndorsementResponseInterface) => {
            this.shopData = response;
      }
    }


这似乎是您想要的-等待第一个请求完成后再开始第二个请求。


Documentation

答案 2 :(得分:0)

您可以使用rxjs的 mergeMap 运算符来完成此操作。

Angular 4.3+(使用HttpClientModule)和RxJS 6 +

getMerchantEndorsement(body): Observable<EndorsementResponseInterface> {
    this.http.post(this.getFullUrl(`/settlement/settlementbanks`, {headers})
      .pipe(mergeMap(character => this.http.get(character.shopId)));
 }

作为参考,您可以查看here