AngularJS摘要循环多久运行一次?

der*_*n14 33 javascript event-handling javascript-events angularjs

在讨论AngularJS的优点时,双向数据绑定经常被吹捧为Angular相对于其他JS框架的主要优点. 深入挖掘,文档表明这个过程是通过脏检查而不是通过事件驱动的措施来完成的.首先,似乎摘要循环的工作原理是在后台以周期性间隔触发方法,$watch在每个周期内检查所有es.然而,进一步阅读,似乎摘要循环实际上是由rootScope.digest()触发的$.apply,而触发又由事件(!)触发,例如通过调用的onClick事件ng-click.

但是,这怎么可能呢?我认为Angular 不使用更改侦听器.那么摘要循环真的如何运作? Angular会在内部自动启动摘要循环,还是由事件触发的摘要循环? 如果摘要循环自动运行,它运行的频率是多少?


一些澄清要点:

  • 我不是在询问手动绑定到更改时摘要循环是如何运行的.在这种情况下,如果要强制使用摘要循环,可以通过调用来执行此操作$.apply()
  • 我也没有询问digest循环响应用户事件的频率.例如,如果ng-model位于输入框中,Angular将在用户开始输入时启动摘要循环.令人困惑的部分是,为了知道用户正在打字,Angular是否在某处使用基于事件的 onKeyUp?
  • 我已经知道每个摘要循环最多有10个循环的限制.我的问题不是关于每个摘要循环的循环次数,而是每秒运行的摘要循环次数.
  • 额外问题:摘要循环与JavaScript事件循环有何关系?JS事件循环是否在后台定期运行?摘要循环与事件循环是一回事,但只在"角度上下文"中?这些完全不同的想法吗?

pix*_*its 13

角度摘要被触发 - 它们不会通过轮询发生.

在代码完成后,代码执行,angular触发摘要.

例:

 element.on('click', function() {
     $scope.$apply(function() { 
         // do some code here, after this, $digest cycle will be triggered
     });
 });
Run Code Online (Sandbox Code Playgroud)

Angular还会在编译/链接阶段后触发$摘要:

Compile > Link > Digest
Run Code Online (Sandbox Code Playgroud)

至于触发了多少个摘要周期?这取决于范围变量稳定的时间.通常至少需要2个周期才能确定.


Rog*_*Jin 12

主要问题的简短直接答案是"NO",角度不会自动触发消化循环.

TL; DR回答:

摘要循环旨在对与Angular范围实例关联的POJO模型运行脏检查,因此只需在模型可能更改时运行.在浏览器内运行的单页Web应用程序中,以下操作/事件可能导致模型更改

  1. DOM事件
  2. XHR响应触发回调
  3. 浏览器的位置发生了变化
  4. 触发器(setTimout,setInterval)触发回调

相应地,Angular触发器摘要循环在例如

  1. 输入指令+ ngModel,ngClick,ngMouseOver等.
  2. $ http和$ resource
  3. $位置
  4. $超时

尝试从我的理解中回答这些奖励问题:

  1. ngModel指令经常与角度输入指令(文本,选择等)一起使用,并且laters将侦听"更改"事件并调用从ngModelController公开的$ setViewValue API以同步返回dom值.在同步过程中,ngModelController将确保触发摘要循环.
  2. 摘要循环不同于JS事件循环,后者是JS运行时的概念(检查出色的可视化会话 https://www.youtube.com/watch?v=8aGhZQkoFbQ),它针对事件队列运行并从队列中删除消耗的事件自动,但摘要循环永远不会从监视列表中删除监视,除非您明确地取消监视.
  3. 每秒摘要循环的数量取决于通过循环执行的所有监视回调的效率.如果一些错误的代码花了一秒钟完成,那么这个摘要循环的花费将超过1秒.

因此,避免角度性能陷阱的一些关键实践是

  1. 监视回调应该编码为尽可能简单/高效,例如将复杂的算法代码分离到例如工作线程
  2. 如果不再使用,请主动移除手表
  3. 更喜欢调用$ scope.$ digest()而不是$ scope.$ apply()如果​​适用,$ digest()只运行范围树的一部分,并确保子树下关联的模型反映到视图中.但$ apply()将针对整个范围树运行,它将遍历更多的监视.