181

我已经使用 AngularJS 一段时间了,并且发现需要每隔一段时间使用一次$timeout (似乎通常是初始化一个 jQuery 插件)。

最近,我一直在尝试更好更深入地了解摘要循环,结果发现了$evalAsync函数。

似乎该函数会产生与 类似的结果$timeout,只是您不要给它延迟。每次我使用$timeout它的延迟都是0,所以现在我想知道我是否应该使用它$evalAsync

两者之间有什么根本区别吗?您会使用哪种情况?我想更好地了解何时使用哪个。

4

2 回答 2

267

我最近在这里基本上回答了这个问题:https ://stackoverflow.com/a/17239084/215945 (该答案链接到与 Misko 的一些 github 交流。)

总结一下:

  • 如果代码使用指令中的 $evalAsync 进行排队,它应该在 Angular 操作 DOM之后,但浏览器呈现之前运行
  • 如果代码使用来自控制器的 $evalAsync 进行排队,它应该在 Angular 操作 DOM之前(以及在浏览器呈现之前)运行——你很少需要这个
  • 如果代码使用$timeout排队,它应该在Angular 操作 DOM之后运行,并且浏览器渲染之后运行(在某些情况下可能会导致闪烁)
于 2013-06-25T17:29:51.783 回答
59

对于那些构建复杂应用程序的人,请注意您的选择会对性能产生影响。另外,我想用更多的技术细节来完成 Mark 的回答:

  • $timeout(callback)将等待当前摘要周期完成(即角度更新所有模型和 DOM),然后它将执行其回调 - 可能会影响角度模型 - 然后$apply在根 $scope 上启动一个完整的,并重新消化一切。

  • 另一方面,$evalAsync(callback)会将回调添加到当前或下一个摘要循环。这意味着如果您在一个摘要循环中(例如在从某个ng-click指令调用的函数中),这将不会等待任何内容,代码将立即执行。如果您在异步调用中,例如 a ,将触发setTimeout一个新的摘要循环 ( )。$apply

因此,就性能而言,调用 总是更好$evalAsync,除非在执行代码之前视图是最新的对您很重要,例如,如果您需要访问某些 DOm 属性,例如元素宽度等。

如果您想了解有关 $timeout、$evalAsync、$digest、$apply 之间区别的更多详细信息,我邀请您阅读我对另一个问题的回答:https ://stackoverflow.com/a/23102223/1501926

另请务必阅读文档

$evalAsync 不保证表达式何时执行,仅保证:

  • 它将在安排评估的函数之后执行(最好在 DOM 渲染之前)。
  • 表达式执行后至少会执行一个 $digest 循环。

注意:如果在 $digest 循环之外调用此函数,则会安排一个新的 $digest 循环。但是,我们鼓励总是在 $apply 调用中调用更改模型的代码。这包括通过 $evalAsync 评估的代码。

于 2015-02-03T00:10:22.847 回答