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

dnc*_*253 178 angularjs angularjs-timeout

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

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

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

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

Mar*_*cok 262

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

总结一下:

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

  • 谢谢你的解释.但有一件事我不确定我理解.如果从控制器或指令调用$ evalAsync,为什么会有所不同?asyncQueue不知道它是从控制器还是指令注册的,它只是在当前范围内排队.它是否与控制器与控制器中运行的东西有关?我只想了解那一部分. (15认同)
  • "来自指令"是指"来自指令的链接功能"吗?或者从指令的链接或控制器方法执行时的行为是否正确? (15认同)
  • 是的,真的不清楚"来自指令"和"来自控制器"是什么意思 (5认同)

flo*_*bon 57

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

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

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

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

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

另外请务必阅读文档:

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

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

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

  • @SridharChidurala因为DOM("HTML")在摘要周期中更新,你必须等到它才能读完mofifications.然而,Angular不鼓励这样做,你应该直接从你的范围读取`x`而不是DOM,所以你不必等待任何事情.另外,你应该更好地使用`ng-style`和css而不是过时的`width`属性.如果您需要更多帮助,请在StackOverflow上打开一个新问题. (2认同)