深入理解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); } }; };
内容版权声明:除非注明,否则皆为本站原创文章。