深入理解Angularjs 脏值检测(10)
下面是关于如何使用$$postDigest函数的:
http://jsbin.com/IMEhowO/1/embed?js,console
异常处理
现有对Scope的实现已经逐渐接近在Angular中实际的样子了,但还有些脆弱,因为我们迄今为止没有花精力在异常处理上。
Angular的作用域在遇到错误的时候是非常健壮的:当产生异常的时候,不管在监控函数中,在$evalAsync函数中,还是在$$postDigest函数中,都不会把digest终止掉。我们现在的实现里,在以上任何地方产生异常都会把整个$digest弄挂。
我们可以很容易修复它,把上面三个调用包在try...catch中就好了。
Angular实际上是把这些异常抛给了它的$exceptionHandler服务。既然我们现在还没有这东西,先扔到控制台上吧。
$evalAsync和$$postDigest的异常处理是在$digest函数里,在这些场景里,从已列入计划的程序中抛出的异常将被记录成日志,它后面的还是正常运行:
Scope.prototype.$digest = function() {
var ttl = 10;
var dirty;
this.$beginPhase("$digest");
do {
while (this.$$asyncQueue.length) {
try {
var asyncTask = this.$$asyncQueue.shift();
this.$eval(asyncTask.expression);
} catch (e) {
(console.error || console.log)(e);
}
}
dirty = this.$$digestOnce();
if (dirty && !(ttl--)) {
this.$clearPhase();
throw "10 digest iterations reached";
}
} while (dirty);
this.$clearPhase();
while (this.$$postDigestQueue.length) {
try {
this.$$postDigestQueue.shift()();
} catch (e) {
(console.error || console.log)(e);
}
}
};
监听器的异常处理放在$$digestOnce里。
Scope.prototype.$$digestOnce = function() {
var self = this;
var dirty;
_.forEach(this.$$watchers, function(watch) {
try {
var newValue = watch.watchFn(self);
var oldValue = watch.last;
if (!self.$$areEqual(newValue, oldValue, watch.valueEq)) {
watch.listenerFn(newValue, oldValue, self);
dirty = true;
}
watch.last = (watch.valueEq ? _.cloneDeep(newValue) : newValue);
} catch (e) {
(console.error || console.log)(e);
}
});
return dirty;
};
现在我们的digest循环碰到异常的时候健壮多了。
http://jsbin.com/IMEhowO/2/embed?js,console
销毁一个监听器
当注册一个监听器的时候,一般都需要让它一直存在于整个作用域的生命周期,所以很少会要显式把它移除。也有些场景下,需要保持作用域的存在,但要把某个监听器去掉。
Angular中的$watch函数是有返回值的,它是个函数,如果执行,就把刚注册的这个监听器销毁。想在我们这个版本里实现这功能,只要返回一个函数在里面把这个监控器从$$watchers数组去除就可以了:
Scope.prototype.$watch = function(watchFn, listenerFn, valueEq) {
var self = this;
var watcher = {
watchFn: watchFn,
listenerFn: listenerFn,
valueEq: !!valueEq
};
self.$$watchers.push(watcher);
return function() {
var index = self.$$watchers.indexOf(watcher);
if (index >= 0) {
self.$$watchers.splice(index, 1);
}
};
};
内容版权声明:除非注明,否则皆为本站原创文章。
