美文网首页
自制前端框架Day21 $evalAsync的实现

自制前端框架Day21 $evalAsync的实现

作者: 蚊子爸爸 | 来源:发表于2017-06-27 16:17 被阅读26次

$evalAsync是什么

顾名思义,延迟执行一段作用于相应scope的eval代码。于timeout的区别是,timeout会把代码交给浏览器去执行,开发者无法控制到底什么时候执行。$evalAsync运行代码是在digest周期内运行的。具体可以通过这个测试案例看的很明白。

  
   it('$evalAsync', function() {
       scope.aValue = 123;
       scope.asyncEvaluated = false;
       scope.asyncEvaluatedImmediately = false;
       var watchFn = function(scope){
           return scope.aValue;
       }
       var listenFn = function(newvalue,oldvalue,scope){
           scope.$evalAsync(function(scope){
               scope.asyncEvaluated = true;//随后执行的
           })
           scope.asyncEvaluatedImmediately = scope.asyncEvaluated;//立即执行的,这时候应该是false
       }
       scope.$watch(watchFn,listenFn);
       scope.$digest();

       expect(scope.asyncEvaluated).toBe(true);
       expect(scope.asyncEvaluatedImmediately).toBe(false);
   });

实现思路

首先在scope里面创建一个延迟eval队列。

function Scope() {
    this.$$watchers = [];
    this.$$lastDirtyWatch = null;
    this.$$asyncQueue = [];
}

调用$evalAsync的时候就把要执行的函数推入这个队列。

Scope.prototype.$evalAsync = function (expr) {
    this.$$asyncQueue.push({ scope: this, expression: expr });
}

在每次digest之前都把这个队列里的函数用当前scope执行一下


Scope.prototype.$digest = function () {
    var dirty;
    var ttl = 10;
    do {
        while (this.$$asyncQueue.length) {
            var asyncTask = this.$$asyncQueue.shift();
            asyncTask.scope.$eval(asyncTask.expression);
        }
        dirty = this.$$digestOnce();
        if (dirty && !(ttl--)) {
            throw "digest次数到达上限依然不稳定"
        }
    } while (dirty);
}

为什么这个while循环放在了digestOnce的前面?

注意的是,这里的while循环放到了$$digestOnce方法的前面,需要解释一下为什么放到了前面:
第一次执行这个digest的时候,是初始化的时候,值肯定是脏的,这时候$$asyncQueue里面是没有东西的,所以直接运行$$digestOnce,运行$$digestOnce的时候,才会执行watcher里面的listenFn,也就是这时候才会把asyncEval注册的方法推入队列,然后scope.asyncEvaluatedImmediately = scope.asyncEvaluated;这段代码会运行,当然是false的。
运行完了以后,跳出digestOnce,因为linstenFn被运行了,所以肯定返回的是dirty,那么就会进行下一次循环,在这次新的循环里,再去运行async队列里面的函数。

如果放在digestOnce后面会怎么样?

详情可以看自己录的自言自语的视频。

相关文章

网友评论

      本文标题:自制前端框架Day21 $evalAsync的实现

      本文链接:https://www.haomeiwen.com/subject/qyqjcxtx.html