Angular 7 / Rxjs:可观察的链接和嵌套

时间:2019-04-22 16:12:48

标签: angular rxjs6 chain

我有一个交易数据集,我想利用给定日期的汇率等其他数据进行充实,然后将其直接发布回我的api。 但是我只得到原始交易而未做任何修改,并且对Angular和Rxjs还是陌生的。因此,我可以向运营商寻求帮助。

我有一个按钮,可以从一个函数调用多个api:

  "Condition": {
    "ForAllValues:StringEquals": {
      "aws:TagKeys": [
        "key1",
        "key2"
      ]
    }
  }

从具有日期的本地api获取所有原始交易。 (有效)

// component.ts
public click() {
    this.deposits = this.depositApi.getAllDeposits()
      .subscribe(
        result => {
          result.map(x => this.depositApi.enrichAndSaveDeposit(x));
        }
      );
  }

在这里,我调用一个外部api以获取给定日期的汇率,然后进行一些计算并将其发布回本地api。

但是它永远不会进入mergeMap部分。

// depositApiService
public getAllDeposits(): Observable<DepositModel[]> {
    return this.http.get<DepositModel[]>(AppConfig.localJsonServerUrl + AppConfig.api.deposits)
      .pipe(
        catchError(this.handleError('getAllDeposits', null))
      );
  }

在此调用了外部api(此方法有效)。

// depositApiService
public enrichAndSaveDeposit(deposit: DepositModel): Observable<DepositModel> {
    return this.apiService.getHistoricEurRate(deposit.date)
      .pipe(
        mergeMap(data => {
          deposit.historicExchangeRate = data.rates.USD;
          deposit.exchangeRate = deposit.sellAmount / deposit.buyAmount;
          deposit.sellAmountInUsd = deposit.sellAmount * data.rates.USD;
          deposit.exchangeRateInUsd = deposit.exchangeRate * data.rates.USD;
          return this.saveLocalDeposit(deposit);
        }), catchError(this.handleError('enrichAndSaveLocalDeposit', deposit))
      );
  }

这是本地api的帖子。 (永远不会到达这一点)

// apiService
public getRemoteExchangeRates(): Observable<ExchangeRateModel> {
    return this.http.get<ExchangeRateModel>(AppConfig.exchangeRateApi + '/latest')
      .pipe(
        catchError(this.handleError('getRemoteExchangeRates', null))
      );
  }

2 个答案:

答案 0 :(得分:2)

这是我对类似问题的回答,概述了如何进行how to build single object from 2 http requests in angular, without adding another value

此外,我想向您提供有关RxJS的提示,我认为这是当前问题的一部分。让我们看一下如下所示的代码。

public click() {
    this.deposits = this.depositApi.getAllDeposits()
      .subscribe(
        result => {
          result.map(x => this.depositApi.enrichAndSaveDeposit(x));
        }
      );
  }

此代码订阅Observable getAllDeposits,然后说当返回带有值时,请使用richAndSaveDeposit映射该值。但是,您的richAndSaveDeposit代码也是一个Observable,因此,正如上面所写的那样,将永远不会被调用,因为它从未被订阅。下面我写了一些可以解决此特定情况的东西。

public click() {
    this.deposits = this.depositApi.getAllDeposits()
      .subscribe(
        result => {
          result.map(x => {
            this.depositApi.enrichAndSaveDeposit(x)
              .subscribe( // this is the subscribe that is needed to make the second part of the chain work
                enrichedResult => {
                  // do something with the enrichedResult here
                }
              );
          };
        }
      );
  }

希望这会有所帮助。

答案 1 :(得分:1)

问题在于您永远不会订阅enrichAndSaveDeposit返回的Observable,因此永远不会进行http POST。

先订阅然后再提供一个Observer函数,甚至是一个空函数,就足够了。

public click() {
    this.deposits = this.depositApi.getAllDeposits()
      .subscribe(
        result => {
          result.map(x => this.depositApi.enrichAndSaveDeposit(x).subscribe(() => {}));
        }
      );
  }

Angular的HttpClient的方法(get,post等)返回冷的Observable,这意味着它们仅在订阅时开始运行。这很重要,原因有两个:

  • 除非您订阅从该HttpClient方法返回的Observable,否则不会发出HTTP请求。
  • 将为每个HttpClient方法的订阅发出一个请求。

阅读以下内容将帮助您了解冷和可观察的观测值之间的区别:

https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339