2013-06-25 71 views
168

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

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

看来这个函数产生的结果与$timeout类似,只是你不给它延迟。每次我使用$timeout它已延迟0,所以现在我想知道如果我应该使用$evalAsync来代替。

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

回答

246

我最近回答基本上是这个问题在这里:(这个答案的链接与MISKO一些github上交换)https://stackoverflow.com/a/17239084/215945

总结:

  • 如果代码是使用$ evalAsync从指令排队,它应该在之后运行DOM已被Angular操纵,但之前浏览器呈现
  • 如果代码是使用$ evalAsync从控制器排队,应该的DOM已被角操作(和浏览器之前渲染)之前运行- 很少做你想做这个
  • 如果代码是使用排队$超时,应该后运行的DOM已被角操纵和后,浏览器呈现(这可能导致闪烁在某些情况下)
+15

谢谢你的解释。有一件事我不确定,但我明白。为什么如果您从控制器或指令中调用$ evalAsync,它会有所作为? asyncQueue不知道它是从控制器还是伪指令注册的,它只是在当前作用域上排队。当一个控制器和一个控制器运行的东西有关吗?我只是想了解那部分。 – dnc253

+0

@ dnc253,我没有看过Angular代码,所以我不知道你的(好)问题的答案。希望别人可以发表评论。 –

+15

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

52

对于构建复杂的应用程序,要知道,有是一个表演im根据您的选择达成协议。另外,我想完成马克的答案与更多的技术细节:

  • $超时(回调)将等待当前消化周期需做(即角更新所有的模型和DOM),然后它将执行回调 - 可能会影响角度模型 - 然后在根目录$范围内启动完整的$apply,并重新设置所有内容。

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

所以在性能方面,它始终是更好地拨打$evalAsync,除非是对你很重要的观点是最新的执行你的代码之前,例如,如果您需要查看在一些DOM的属性,例如元素宽度等。

如果你想约$超时之间的区别更多的细节,$ evalAsync,$消化,$申请,我请你阅读上的其他问题我的回答:https://stackoverflow.com/a/23102223/1501926

此外,一定要阅读documentation

的$ evalAsync不保证何时表达式将被执行到,只有:

  • 将是计划的评判的功能后执行n(最好在DOM渲染之前)。
  • 在表达式执行后至少会执行一个$ digest循环。

注:如果这个函数被调用摘要$周期之外,一个新的$消化周期将被安排。但是,鼓励始终调用在$ apply调用中更改模型的代码。这包括通过$ evalAsync评估的代码。

+0

你能解释为什么需要访问某些DOM属性时需要$ timeout 。假设我有

ng-bind的watch函数不更新内存中的dom属性,我知道在摘要循环退出之前,它没有机会重新绘制视图。 –

+2

@SridharChidurala由于DOM(“HTML”)在摘要周期内更新,所以您必须等待它完成后再阅读修改。然而,Angular不鼓励这样做,你应该从你的范围直接读取'x'而不是DOM,所以你不必等待任何东西。此外,你应该更好地使用'ng样式'与CSS而不是过时的'width'属性。如果您需要更多帮助,请在StackOverflow上打开一个新问题。 – floribon