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


180

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

最近,我一直在尝试更好地和更深入地了解摘要循环,并遇到了$ evalAsync函数。

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

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

Answers:


263

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

总结一下:

  • 如果使用指令中的$ evalAsync将代码放入队列中,则该代码应 Angular处理DOM 之后浏览器呈现之前运行
  • 如果代码是使用$ evalAsync从控制器中排队的,则它应该 Angular操作DOM之前(以及在浏览器呈现之前)运行-您很少需要这样做
  • 如果代码使用$ timeout排队,则应 Angular处理DOM 之后以及浏览器渲染之后运行代码(在某些情况下可能导致闪烁)

15
谢谢你的解释。一件事我不确定我是否明白。如果从控制器或指令调用$ evalAsync,为什么会有所不同?asyncQueue不知道它是从控制器还是在指令中注册的,它只是将其在当前作用域中排队。当东西在控制器中运行时与控制器有关系吗?我只想了解那部分。
dnc253 2013年

@ dnc253,我没有看过Angular代码,所以我不知道您的(好)问题的答案。希望其他人可以发表评论。
Mark Rajcok 2013年

15
“来自指令”是指“来自指令的链接功能”吗?还是从指令的链接或控制器方法执行时的行为正确吗?
SimplGy 2014年

5
是的,现在还不清楚“来自指令”和“来自控制器”的含义
刺̈2015年

1
@MarkRajcok,能否在这里澄清一下:如果代码是使用$ evalAsync指令排队的,那么它应该在Angular操作 DOM之后运行-应该在此指令或其他指令操纵DOM之后运行吗?
Max Koretskyi 2015年

59

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

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

  • 另一方面,$ 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评估的代码。


您能否解释一下为什么需要访问某些DOM属性时需要$ timeout的原因?假设我有<table width =“ {{x}}”> ng-bind的watch函数不更新内存中的dom属性,我知道在摘要循环结束之前,它没有机会重新绘制视图。
Sridhar Chidurala

2
@SridharChidurala,因为DOM(“ HTML”)在摘要周期中进行了更新,因此您必须等待它完成后才能阅读主题。但是,Angular不建议这样做,您应该x直接从范围而不是DOM中读取内容,因此您不必等待任何事情。另外,您最好将ng-stylecss与过时的width属性一起使用。如果您需要更多帮助,请在StackOverflow上打开一个新问题。
floribon 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.