AngularJS中的$ evalAsync和$ timeout之间有什么区别?

时间:2013-06-25 15:36:36

标签: angularjs angularjs-timeout

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

最近,我一直在努力更好,更深入地了解摘要周期,并且我遇到了$evalAsync函数。

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

两者之间是否存在根本差异?你会用哪种情况比另一种情况多?我想更好地了解何时使用哪一个。

2 个答案:

答案 0 :(得分:256)

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

总结:

  • 如果代码使用 $ evalAsync从指令排队,它应该在之后运行在Angular操纵DOM之后,但之前浏览器渲染
  • 如果代码使用 $ evalAsync从控制器排队,它应该在之前运行 DOM由Angular操纵(并且在浏览器渲染之前) - 很少做你想要这个
  • 如果代码使用 $ timeout 进行排队,则应该在之后运行在Angular操作DOM之后运行,然后在浏览器渲染之后运行在某些情况下可能会导致闪烁)

答案 1 :(得分:57)

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

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

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

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

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

另请务必阅读documentation

  

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

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

注意:如果在$ digest周期之外调用此函数,则会安排新的$ digest周期。但是,建议始终在$ apply调用中调用更改模型的代码。这包括通过$ evalAsync评估的代码。