与AngularJS的约会之事件循环+watchers源码分析

ng中说到事件轮询,第一个拿出来的肯定是digest函数啦,在digest()的事件轮询中,一共会轮询两个列表,一个为AsyncEvalQueue,一个为Watchers列表,apply方法进入ng上下文执行的Callback fn将其context修改为ng的控制域,先从queue取出每一个asyncTask,获取其scope通过*eval方法进行callbackfn目标的expression计算,以及修改值引起$watch的调用,导致监听器被触发,dirtycheck在digest()中执行,遍历watchers列表,当有newvalue出现时触发监听器listenerFn的回调修改model并重新绘制dom节点,然后再将脏值置位,即还要进行一次dirtycheck才可以判断数据已经稳定,当且仅当数据稳定时digest才算执行完毕,即queue为空且watchers列表的所有值的脏值都为false,即不需要进行过多的检测了,已经稳定(ttl=10)最多检测次数为ttl设定值。
代码如下:(AsyncQueue的遍历读取)

lastDirtyWatch = null;
        do { // "while dirty" loop
          dirty = false;
          current = target;
          //下面开始对异步队列进行轮询处理
          //在promise进行回调操作就是基于这个轮询
          while(asyncQueue.length) {
            try {
              asyncTask = asyncQueue.shift();
              asyncTask.scope.$eval(asyncTask.expression);
            } catch (e) {
              clearPhase();
              $exceptionHandler(e);
            }
            lastDirtyWatch = null;
          }
//这里就是著名的脏值检测啦,把所有的watchers都轮询一遍
(dirty check)
do { // "traverse the scopes" loop
           if ((watchers = current.$$watchers)) {
              // process our watches
              length = watchers.length;
              while (length--) {
                try {
                  watch = watchers[length];
                  // Most common watches are on primitives, in which case we can short
                  // circuit it with === operator, only when === fails do we use .equals
                  if (watch) {
                    if ((value = watch.get(current)) !== (last = watch.last) &&
                        !(watch.eq
                            ? equals(value, last)
                            : (typeof value == 'number' && typeof last == 'number'
                               && isNaN(value) && isNaN(last)))) {
                      dirty = true;
                      lastDirtyWatch = watch;
                      watch.last = watch.eq ? copy(value) : value;
                      watch.fn(value, ((last === initWatchVal) ? value : last), current);
                      //ttl的一个判断
                      if (ttl < 5) {
                        logIdx = 4 - ttl;
                        if (!watchLog[logIdx]) watchLog[logIdx] = [];
                        logMsg = (isFunction(watch.exp))
                            ? 'fn: ' + (watch.exp.name || watch.exp.toString())
                            : watch.exp;
                        logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
                        watchLog[logIdx].push(logMsg);
                      }
                      if (watch.get.$$unwatch) stableWatchesCandidates.push({watch: watch, array: watchers});
                    } else if (watch === lastDirtyWatch) {
                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
                      // have already been tested.
                      dirty = false;
                      break traverseScopesLoop;
                    }
                  }
                } catch (e) {
                  clearPhase();
                  $exceptionHandler(e);
                }
              }
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值