详解AngularJS脏检查机制及$timeout的妙用

浏览器事件循环和Angular的MVW
“脏检查”是Angular中的核心机制之一,它是实现双向绑定、MVVM模式的重要基础。
Angular将双向绑定转换为一堆watch表达式,然后递归检查这些watch表达式的结果是否变了,如果变了,则执行相应的watcher函数。等到Model的值不再变化,也就不会再有watcher函数被触发,一个完整的digest循环就结束了。
因为我们不需要改变编程思维,就能用相同的语言、相同的事件模型,快速开发NodeJS程序,所以NodeJS迅速火起来,JavaScript full-stack也日渐流行。
我们经常听说Angular是一个MV*的框架,这是因为Angular拓展了浏览器的事件模型,建立了一个自己的上下文环境。
||Angular中的$watch函数
watch表达式很灵活:可以是一个函数,可以是$scope上的一个属性名,也可以是一个字符串形式的表达式。$scope上的属性名或表达式,最终仍会被$parse服务解析为响应的获取属性值的函数。
所有的watcher函数都会被unshift函数插入scope.$$watchers数组的头部,以便后边的$digest使用。
最后,$watch函数会返回一个反注册函数,一旦我们调用它,就可以移除刚才注册的watcher。
需要注意的是,Angular默认是不会使用angular.equals()函数进行深度比较的,因为使用===比较会更快,所以,它对数组或者Object进行比较时检查的是引用。这就导致内容完全相同的两个表达式被判定为不同。如果需要进行深度比较,第三个可选参数objectEquality,需要显式设置为true,如$watch('someExp', function(){...}, true)。
Angular还提供了$watchGroup、$watchCollection方法来监听数组或者是一组属性。
||Angular中的$digest函数
前面提到Angular拓展了浏览器的事件循环,这是怎么回事呢?
当接受View上的事件指令所转发的事件时,就会切换到Angular的上下文环境,来相应这类事件,$digest循环就会触发。
$digest循环实际上包括两个while循环。它们分别是:处理$evalAsync的异步运算队列,处理$watch的watchers队列。
当$digest循环发生的时候,它会遍历当前$scope及其所有子$scope上已注册的所有watchers函数。
遍历一遍所有watcher函数称为一轮脏检查。执行完一轮脏检查,如果任何一个watcher所监听的值改变过,那么就会重新再进行一轮脏检查,直到所有的watcher函数都报告其所监听的值不再变了。
当$digest循环结束时,才把模型的变化结果更新到DOM中去。这样可以合并多个更新,防止频繁的DOM属性。
需要注意的是,在$digest循环结束之前,如果超过了10轮脏检查,就会抛出一个异常,以防止脏检查无限循环下去。
什么时候会进入这个Angular的上下文环境,触发“脏检查机制”呢?这个问题很重要,它同时也是比较让人头疼的地方。
每一个进入Angular上下文环境的事件,都会执行一次$digest循环。对于ngModel监听的表单交互控件来说,每输入一个字符,就会触发一次循环来检查$watcher函数,以便及时更新View。在Angular1.3之后可以利用ngModelOptions进行配置,来修改默认的触发方式。
||Angular中的$apply
$digest是一个内部函数,正常的应用代码中是不应该直接调用它的。要想主动触发它,就要调用scope.$apply函数,它是触发Angular“脏检查机制”的常用公开接口。
需要注意的是:Angular只能管理它所已知的行为触发方式,而不能涵盖所有的Angular操作场景。这就为什么我们在封装第三方jQuery插件时,不能自动更新视图,而需要我们手动调用$scope.$apply。
集成jquery插件的时候,有时会出现digest in progress错误。如果排除Bug之后仍然不能解决,那么可以考虑用$timeout来解决。

$timeout的妙用

angular.js的$timeout指令对window.setTimeout做了一个封装,它的返回值是一个promise对象.当定义的时间到了以后,这个promise对象就会被resolve,回调函数就会被执行.

如果需要取消一个timeout,调用$timeout.cancel(promise)方法.

用法:

$timeout(fn, [delay], [invokeApply]);

fn: 回调函数(必填)

delay: number类型.延迟的时间(非必填),如果不填,表示等线程空下来以后就执行.比如当页面被渲染完成后.

invokeApply: 布尔值.是否需要进行脏值检测(非必填),不填默认为false,如果设置为true,则fn回调会被包在$scope.$apply()中执行

返回值: 返回一个promise对象.当定义的时间到了以后,这个promise对象就会被resolve.resolve的值就是fn回调函数的返回值


$timeout可以实现当页面被渲染完成后再执行函数,这个其实不是$timeout的东西,而是window.setTimeout的原理。

因为执行页面渲染是异步的,如果要执行的代码要等到页面渲染完成后才能执行,那么就要把这段代码也弄成异步,才能保证代码的执行顺序。在js中,让同步代码也异步.即加上settimeout.

详见:settimeout(0)的作用

使用setTimeout解决ui线程阻塞问题    

使用setTimeout解决ui线程阻塞问题补充案例

在延时任务中修改被绑定到界面中的变量,那么window.setTimeout是不会触发“脏检查”来更新UI界面的。你可能想:加上$scope.$apply不就解决了嘛。是的,这能解决UI界面更新的问题,但是你可能会遇到另一个问题:
 Error: $digest already in progress
这是怎么回事儿?哦,Angular内部正在进行“脏检查”。一位聪明的程序员巧妙地写了下面一段代码来解决这个问题:


function safeApply(scope, fn){ 
  (scope.
phase||scope.$root.
phase) ? fn() : scope.$apply(fn); 
}
代码中,在执行apply函数之前会首先检查Angular内部是不是正在做“脏检查”,如果是就直接执行函数,不用$apply;反之没有启动脏检查,那么就$apply执行该函数。呵呵,“完美”解决,不是吗?
请注意,笔者在上面的完美两个字上加了引号。Angular已经为我们内置了$timeout服务,它是Angular包装原生javascript window.setTimeout而实现的。
$timeout有很多妙用,但一定不要滥用,$timeout实现apply功能不应该是我们的第一方案,第一方案仍然应该是使用Angular内置的指令。






 


$digest循环会运行多少次?


当一个$digest循环运行时,watchers会被执行来检查scope中的models是否发生了变化。


如果发生了变化,那么相应的listener函数就会被执行。这涉及到一个重要的问题。


如果listener函数本身会修改一个scope model呢?AngularJS会怎么处理这种情况?


 


答案是$digest循环不会只运行一次。在当前的一次循环结束后,它会再执行一次循环


用来检查是否有models发生了变化。这就是脏检查(Dirty Checking),它用来处理在l


istener函数被执行时可能引起的model变化。因此,$digest循环会持续运行直到model


不再发生变化,或者$digest循环的次数达到了10次。因此,尽可能地不要在listener函数中修改model。


 


Note: $digest循环最少也会运行两次,即使在listener函数中并没有改变任何model。


正如上面讨论的那样,它会多运行一次来确保models没有变化。






原文地址


http://www.sitepoint.com/understanding-angulars-apply-digest/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值