首页 > 解决方案 > 如何在参数更改时重新执行异步可观察?

问题描述

我有一个简单的异步 observable,它需要 2 个参数来执行一些计算:

  public preferredCurrency: string = '';

  wmData$ = this.http.get<any>("./api/wealthModeling/GetWMData");
  portfolioCalculation$ = this.wmData$.pipe(
    mergeMap((wmData) => {
      return this.portfolioCalculationService.getPortfolioValues(wmData, this.preferredCurrency);
    })

正如您在初始加载时看到的,preferredCurrency 为空,但是 UI 允许用户选择不同的货币(通过下拉菜单),因此需要再次执行计算。

我无法找到portfolioCalculation$再次执行的方法。

希望这能解释我想要实现的目标。

非常感谢。

标签: angularasync-awaitrxjsbehaviorsubjectrxjs-observables

解决方案


为了详细说明我的评论,这里有一个示例,说明如何使用 BehaviorSubject 来实现这一点。

@Component({/*...*/})
export class YourComponent {
  // This is the BehaviorSubject we will 'next' on, whenever preferredCurrency changed
  // Replace 'initial' by your initial preferredCurrency
  public preferredCurrency$:BehaviorSubject<string> = new BehaviorSubject('Initial');

  private wmData$ = this.http.get<any>("./api/wealthModeling/GetWMData").pipe(
    // Include this if your wmData is the same for all preferredCurrency (this will make it so that the HttpRequest is only performed once)
    // shareReplay(1)
  );

  // pipe from your preferredCurrency$ subject - we will 'next' to it whenever a new preferredCurrency is selected, thus starting this chain
  public portfolioCalculation$ = this.preferredCurrency$
    .pipe(
      // you don't need this, since BehaviorSubjects already start with a value (include if Observable without initial value is used instead)
      // startsWith('initial'),

      // We want to switch to the HTTP Request observable (whenever preferredCurrency was changed)
      switchMap(currency => this.wmData$.pipe(
        mergeMap(wmData => this.portfolioCalculationService.getPortfolioValues(wmData, this.preferredCurrency)) 
      )) 
    );

  // Call this method (or run the statement inside directly) whenever your preferredCurrency changed
  public changePreferredCurrency(newPreferredCurrency:string):void {
    this.preferredCurrency$.next(newPreferredCurrency);
  }
}

在这种情况下,任何在您的更改时触发的 Observable 都可以代替 BehaviorSubjectpreferredCurrency用作​​ Source Observable(例如,如果您使用@angular/forms,则每个控件都有一个valueChangesObservable)。只要记住将一个startsWith('initial')运算符作为您链中的第一个运算符,以防 Observable 不产生初始值(例如 @angular/formsvalueChanges不产生初始值)。


推荐阅读