【问题标题】:Angular ngFor calling a function which returns an ObservableAngular ngFor 调用一个返回 Observable 的函数
【发布时间】:2019-02-17 19:24:10
【问题描述】:

我正在使用一个函数来返回一个 Observable,然后在模板中使用异步管道,但这会导致成千上万的网络请求并使浏览器崩溃。我确信这很明显,但是我是 Angular 的新手。我在 stackblitz 上创建了一个示例:

https://stackblitz.com/edit/angular-mvpknj

<h1>Todos</h1>
<<ul>
  <li *ngFor="let todo of completedTodos | async" >{{ todo.title }}</li>
  <!-- <li *ngFor="let todo of getCompletedTodos() | async" >{{ todo.title }}</li> -->
</ul>

未注释的行可以正常工作,因为它引用的是类变量而不是函数。

如果您取消注释使用 getCompletedTodo 函数的 *ngFor,它只会炸毁浏览器。

【问题讨论】:

  • 这是一个很好的例子,说明为什么在模板中应该避免函数表达式,因为 Angular 会多次调用它们,如果其他属性发生变化,然后再调用多次。您将结果分配给类属性的方法比函数表达式更有效。这不仅仅是因为 ngFor,这与 Angular 和变更检测有关。尝试对原始数据做同样的事情,并记录它被函数表达式调用的次数。这就是为什么在很多情况下都推荐使用 Pipe 的原因,因为它可以缓存结果。

标签: angular typescript rxjs


【解决方案1】:

我认为原因是,当 for 循环迭代时,对于每次迭代,都会执行 getCompletedTodo() 方法,该方法调用 API,它会继续发送请求,正如您在浏览器工具中看到的那样,因此会失败打开浏览器。

【讨论】:

  • yap 我认为@dileepkumar jami 是对的。 getCompletedTodo() 函数一次又一次地执行。我已经在开发者的工具中展示了。
  • 不是因为循环迭代,而是因为角度变化检测。有很多文章和文档涵盖了机制以及如何优化渲染和性能。基本上避免模板中的函数调用有助于避免像这样严重的性能/内存问题。
  • 这和变化检测无关,去把getCompletedTodo()方法改成console.log,你会看到它只记录了几次。这与 Observable 有关。我已对其进行了更新,因此 getCompletedTodo() 函数返回类变量而不是调用服务。 stackblitz.com/edit/…
【解决方案2】:

我稍微修改了您的代码。您可以在此StackBlitz 中找到它。据我所知,它只执行了一次。

【讨论】:

  • 当getCompletedTodos()返回appService.completedTodos()时出现问题;
  • 我完全删除了(实际上是注释掉了)那个函数。
  • 我了解您所做的更改,但是我需要能够调用函数并将参数传递给它,我创建的代码只是一个示例
  • 我明白了。我相信你有一个有效的用例。但我可以根据经验告诉你,使用函数会导致 Angular 多次执行它。所以我很少在这种情况下使用函数。您可以尝试的一件事是阻止标记的呈现,直到在组件中设置了某些变量,使用类似 *ngIf="dataIsPresent" 的东西。
  • 好吧,看看 cmets,我可能应该只引用一个类变量,我想如果我创建几个新组件而不是尝试做一个,我应该能够实现这一点。谢谢
猜你喜欢
  • 2021-07-26
  • 2017-04-29
  • 2017-03-12
  • 2020-10-10
  • 2019-09-08
  • 1970-01-01
  • 1970-01-01
  • 2016-12-12
  • 1970-01-01
相关资源
最近更新 更多