Angular源码解析4——作用域上代码的执行

在作用域中执行代码

  1. $eval

    1
    2
    3
    4
    5
    6
    7
    8
    /**
    *$eval接收2个参数
    *fn需要在作用中执行的函数
    *(可选)传入的参数
    **/
    Scope.prototype.$eval=function (fn,locals) {
    return fn(this,locals);
    }
  2. $apply
    有时候我们需要执行与Angular无关的方法(比如window.setInerval),但是这些方法改变了作用域中的数据,我们希望监听到这些变化,这时候我们需要通过$apply传入方法。

    1
    2
    3
    4
    5
    6
    7
    8
    Scope.prototype.$apply=functin (fn) {
    try {
    return this.$eval(fn);
    } finally {
    //$digest的执行放在finally中,以确保即使报错也会执行
    this.$digest();
    }
    }
  3. 延迟执行的函数
    在angular中我们可以用$apply传递一个计时器(setInterval)来实现延迟执行函数,也可以调用内部的$interval和$timeout。Angular中还有一种延迟执行的方法$evalAsync。

$evalAsync会将一个函数推入计划中。这个函数会在这次$digest或者下次$digest之前执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//在Scope中定义任务队列
function Scope () {
this.$$watchers=[];
this.$$asyncQueue=[];
}
//定义$evalAsync,传入需要延迟执行的函数
Scope.prototype.$evalAsync=function (fn) {
this.$$asyncQueue.push({scope:this,expression:fn});
}
Scope.prototype.$digest=function () {
var time=10;
var dirty;
do {
while (this.$$asyncQueue.length) {
var task=this.$$asyncQueue.shift();
this.$eval(task.expression);
}
dirty=this.$$digestOnce();
if (dirty &&!(time--)) {
throw '已到10次脏值查询'
}
} while (dirty);
}