【问题标题】:Angular 2 - Endless loop in async pipeAngular 2 - 异步管道中的无限循环
【发布时间】:2017-05-07 01:12:39
【问题描述】:

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

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

这是函数:

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

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

【问题讨论】:

    标签: angular pipe


    【解决方案1】:

    每次调用都会从myAsyncFunc(i: string) 返回一个新的 Promise,这就是为什么会出现“无限循环”。尝试返回相同的 Promise 实例;-)

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

    【讨论】:

    • 感谢您的回答...所以我必须在每个项目上设置 Promise 实例?或者我如何返回相同的实例?
    • 您要么必须缓存每个 i 的承诺(例如在地图对象中),要么只需将承诺附加到 i 本身(我个人还是喜欢拥有专用的视图模型)。
    • @JohannesRudolph 拯救了我的一天 :) !
    • @JohannesRudolph 有这样做的简单示例吗?仍然无法弄清楚如何做到这一点......谢谢
    • 没有例子怎么可能是答案。
    【解决方案2】:

    您可以查看我关于这个特定主题的博文,当它遇到我们的项目时消耗 5GB od 浏览器 RAM :)
    我是here

    解决此问题的最简单方法是(如前所述)不要直接在模板中使用函数返回的 Promise:{{ getPromise(id) | async }},而是将此 Promise 存储在控制器中(.ts 文件)并在视图中引用它。
    此外,这可以通过将更改检测设置更改为 push-pull 来治愈,但在我看来,它带来的弊大于利。

    【讨论】:

      【解决方案3】:

      如果你的 async/observable 需要你传递一个参数(例如,你在一个 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>
      

      【讨论】:

        【解决方案4】:

        一种解决方法是使用Memoizee

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

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

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

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

        【讨论】:

          猜你喜欢
          • 2021-09-28
          • 2019-10-04
          • 2017-04-04
          • 1970-01-01
          • 2017-12-11
          • 1970-01-01
          • 2020-05-11
          • 1970-01-01
          • 2017-05-05
          相关资源
          最近更新 更多