从 HTML 模板调用异步函数(Retunes Observable)

MCM*_*tan 3 javascript rxjs typescript angular

HTML 模板上显示的数据是关键表单数据。意思是,它需要被翻译。为此,我想从我的模板中调用 Async 函数。试过了,没有成功:

模板:

<span class="myClass-rowValue">{{translateServingStyle(size.defaultServingStyle?.surcharge) | async}}</span>
Run Code Online (Sandbox Code Playgroud)

组件 ts 文件:

servingStylesData$: Observable<ServingStyles_servingStyles[]>;

ngOnInit(): void {
    this.servingStylesData$ = of(this._apollo
      .watchQuery<ServingStyles>({
        query: ServingStylesQuery
      }))
      .pipe(
        filter((query) => !!query),
        switchMap((query) => query.valueChanges),
        take(1),
        takeUntil(this._ngOnDestroy),
        map((response) => response.data.servingStyles)
      );
}

translateServingStyle(servingStyleValue: string): Observable<string> {
    return this.servingStylesData$
      .pipe(
        map((servingStyles) => servingStyles
          .filter((servingStyle) => servingStyle.value === servingStyleValue)
          .map((selectedServingStyle) => selectedServingStyle.value)[0]
          )
      );
  }
Run Code Online (Sandbox Code Playgroud)

这样做的确切原因是什么?

# 编辑

这使我的浏览器崩溃。进入无限循环调用translateServingStyle()

我尝试删除我的函数代码,然后返回

of("some string")
Run Code Online (Sandbox Code Playgroud)

它工作正常。

但是当将管道引用到本地变量时,就会发生这个循环。任何人都可以请解释为什么?

Jul*_*bos 5

tl;dr 不要在函数调用中使用异步管道。这是昂贵且长时间运行的,并且可能会破坏用户体验或在您的情况下使您的浏览器崩溃:您自己管理您的 observables 而不是使用易于使用的 async管道。

如果您仍然想使用async带有函数的管道,您可以尝试使用ChangeDetectionStrategy.OnPush。这带来了其他缺点,例如手动运行更改检测,例如 withthis.cdr.detectChanges();cdrbe of type ChangeDetectorRef


请注意 Angulars Lifecycle 系统的工作原理。

由于评估的函数值没有内部引用(Angular 使用它来检查值是否已更改或需要更新),因此生命周期钩子不会检查它们ngOnChanges,而是使用ngDoCheck,它会运行很多次

这对于管道来说尤其糟糕,对于异步管道来说最糟糕。如果我们称您对async管道的使用成本高昂且运行时间长,Angular 指出:

昂贵且长时间运行的管道可能会破坏用户体验

或者在您的情况下使浏览器崩溃。

请查找此博客文章以获取进一步说明。