Angular 2 - 异步管道中的无限循环

时间:2016-12-21 14:58:18

标签: angular pipe

当我尝试绑定像这样的异步函数时,我得到一个无限循环:

<tr *ngFor="let i of items">
     <td>{{myAsyncFunc(i) | async}}</td>
</tr>

这是功能:

private myAsyncFunc(i: string): Promise<string> {
        return Promise.resolve("some");
}

我做错了什么?或者这是一个错误?

4 个答案:

答案 0 :(得分:12)

您在每次通话时都会从myAsyncFunc(i: string)返回新的承诺,这就是您获得无限循环的原因&#34;。尝试返回相同的Promise实例; - )

&#34;无限循环&#34;实际上并不是传统的无限循环,而是async管道在其输入Promise结算时触发更改检测周期的副作用。在这个新的变化检测周期中,angular将调用myAsyncFunc(i: string)并获得一个新的Promise来观察,然后解决整个事情再次开始。

答案 1 :(得分:0)

当我们的项目耗费5GB od浏览器内存时,你可以查看我关于这个特定主题的博客文章:) 它是here

解决此问题的最简单方法是(如前所述)不要在模板中使用函数返回的promise:{{ getPromise(id) | async }}但是将此承诺存储在控制器(.ts文件)中并参考它在视野中 此外,这可以通过将变化检测设置更改为push-pull来治愈,但在我看来,它会带来更多的邪恶而不是好的。

答案 2 :(得分:0)

如果您的异步/可观察对象要求您传递参数(例如,您位于ngFor循环中),则可以为此创建一个自定义异步管道。

@Pipe({
  name: 'customPipe'
})
export class customPipe implements PipeTransform {

  constructor(private someService: SomeService) {}

  /**
   * 
   * @param id 
   */
  transform(id: number): Observable<boolean> {
    return this.someService.shouldShow(id);
  }

}

在模板中,您可以将异步管道称为:

<td>{{id | customPipe | async}}</td>

答案 3 :(得分:0)

一种解决方法是使用 Memoizee

您可以按照 here 的说明创建自定义装饰器来记忆您的函数。之后,您可以按如下方式编写函数:

@memoize()    
private myAsyncFunc(i: string): Promise<string> {
        return Promise.resolve("some");
}

这会缓存最初返回的 Promise,当 async 管道重新检查 Promise 的状态时,它将获得缓存的 Promise 而不是新的。

注意记忆函数的缓存效果。

相关问题