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

时间:2014-08-07 08:30:05

标签: javascript angularjs javascript-events event-handling

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

但是,这怎么可能呢?我认为Angular doesn't use change listeners。那么摘要循环真的如何运作? Angular会在内部自动启动摘要循环,还是由事件触发的摘要循环?如果摘要循环自动运行,它的运行频率是多少?


一些澄清要点:

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

3 个答案:

答案 0 :(得分:13)

角度摘要被触发 - 它们不会通过民意调查发生。

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

示例:

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

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

Compile > Link > Digest

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

答案 1 :(得分:12)

对主要问题的简短直接回答是" NO",angular不会自动触发摘要循环。

TL; DR回答:

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

  1. DOM活动
  2. XHR响应触发回调
  3. 浏览器的位置更改
  4. 定时器(setTimout,setInterval)触发回调
  5. 相应地,Angular触发器摘要循环,例如

    1. 输入指令+ ngModel,ngClick,ngMouseOver等
    2. $ http和$ resource
    3. $ location
    4. $超时
    5. 尝试从我的理解中回答这些奖励问题:

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

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

答案 2 :(得分:4)

我相信这就是发生的事情。 AngularJS巧妙地假设模型变化仅发生在用户交互上。这些相互作用可能由于

而发生
  • 鼠标活动(移动,点击等)
  • 键盘活动(按键,按键等)

相应事件的AngularJS指令将表达式执行包装在$ scope。$ apply中,如@pixelbits所示。这导致了消化循环。

还有一些其他事件,AngularJS触发摘要循环。 $ timeout服务和$ interval服务是两个这样的例子。包含在这些服务中的代码也会导致运行摘要循环。 可能有一些其他事件\服务可以导致执行摘要周期,但这些是主要的。

这就是Angular上下文之外的模型更改不会更新监视和绑定的原因。所以需要显式调用$ scope。$ apply。我们在与jQuery插件集成时一直这样做。

相关问题