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

问题描述 投票:1回答:2

我有一个交易数据集,我想用额外的数据,如给定日期的汇率,并将其直接发回我的api。但是我只是在没有任何修改的情况下得到我的原始交易,而且我还是Angular和Rxjs的新手。所以我可以对运营商使用一些帮助。

我有一个按钮,从一个函数调用几个apis:

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

获取当地api的所有原始交易,这些交易都有日期。 (这个有效)

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

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

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

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

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

// depositApiService
private saveLocalDeposit(deposit: DepositModel): Observable<DepositModel> {
    return this.http.post<DepositModel>
      (
        AppConfig.localJsonServerUrl + AppConfig.api.deposits,
        deposit,
        { headers: new HttpHeaders().set('Accept', 'application/json') }
      )
      .pipe(
        catchError(this.handleError('saveLocalDeposit', deposit))
      );
  }
angular rxjs6 chain
2个回答
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,然后说当返回值时,使用enrichAndSaveDeposit映射该值。但是,您的enrichAndSaveDeposit代码也是一个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
投票

问题是你永远不会订阅从enrichAndSaveDeposit返回的Observable,因此永远不会发出http POST。

订购然后提供观察员功能,即使是空的,也足够了。

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

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

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

阅读以下内容将有助于您了解冷热Observables之间的区别:

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

© www.soinside.com 2019 - 2024. All rights reserved.