AngularJS-源码阅读(八.二)
2019独角兽企业重金招聘Python工程师标准>>>
$digest: function() {var watch, value, last,watchers,asyncQueue = this.$$asyncQueue,postDigestQueue = this.$$postDigestQueue,length,dirty, ttl = TTL,next, current, target = this,watchLog = [],logIdx, logMsg, asyncTask;//beginPhase和clearPhase 用来进行状态管理beginPhase('$digest');lastDirtyWatch = null;do { // "while dirty" loopdirty = false;current = target;while(asyncQueue.length) {try {asyncTask = asyncQueue.shift();asyncTask.scope.$eval(asyncTask.expression);} catch (e) {clearPhase();$exceptionHandler(e);}lastDirtyWatch = null;}traverseScopesLoop:do { // "traverse the scopes" loopif ((watchers = current.$$watchers)) {// process our watcheslength = 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 .equalsif (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);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);}} 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);}}}// Insanity Warning: scope depth-first traversal// yes, this code is a bit crazy, but it works and we have tests to prove it!// this piece should be kept in sync with the traversal in $broadcastif (!(next = (current.$$childHead ||(current !== target && current.$$nextSibling)))) {while(current !== target && !(next = current.$$nextSibling)) {current = current.$parent;}}} while ((current = next));// `break traverseScopesLoop;` takes us to hereif((dirty || asyncQueue.length) && !(ttl--)) {clearPhase();throw $rootScopeMinErr('infdig','{0} $digest() iterations reached. Aborting!\n' +'Watchers fired in the last 5 iterations: {1}',TTL, toJson(watchLog));}} while (dirty || asyncQueue.length);clearPhase();while(postDigestQueue.length) {try {postDigestQueue.shift()();} catch (e) {$exceptionHandler(e);}}},$destroy: function() {// we can't destroy the root scope or a scope that has been already destroyedif (this.$$destroyed) return;var parent = this.$parent;this.$broadcast('$destroy');this.$$destroyed = true;if (this === $rootScope) return;forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;// This is bogus code that works around Chrome's GC leak// see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =this.$$childTail = null;},$eval: function(expr, locals) {return $parse(expr)(this, locals);},$evalAsync: function(expr) {// if we are outside of an $digest loop and this is the first time we are scheduling async// task also schedule async auto-flushif (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {//$browser.defer 把这个看做setTimout$browser.defer(function() {if ($rootScope.$$asyncQueue.length) {$rootScope.$digest();}});}this.$$asyncQueue.push({scope: this, expression: expr});},$$postDigest : function(fn) {this.$$postDigestQueue.push(fn);},//执行完expr,会$digest一遍。//这样做得好处是,expr的执行不会影响到$digest$apply: function(expr) {try {beginPhase('$apply');return this.$eval(expr);} catch (e) {$exceptionHandler(e);} finally {clearPhase();try {$rootScope.$digest();} catch (e) {$exceptionHandler(e);throw e;}}},//$broadcast,$on,$emit 省略掉//$broadcast,$emit 的作用就是,沿着Scope的关系上下注册的事件,事件的格式要注意一下//{// name: name,// targetScope: scope,// stopPropagation: function() {stopPropagation = true;},// preventDefault: function() {// event.defaultPrevented = true;// },// defaultPrevented: false// },这些可以用来阻止事件的冒泡//$on的事件存储在每个$scope中的 $$listeners对象中,可以多次$on同一个namevar $rootScope = new Scope();return $rootScope;//类似于java中的线程锁的概念function beginPhase(phase) {if ($rootScope.$$phase) {throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);}$rootScope.$$phase = phase;}function clearPhase() {$rootScope.$$phase = null;}}
看到这里,可以看出angularJS以响应status变化的模式(具体的学术性名称忘掉了)来做监控,在js中,这会导致随着status的增多,监控会越来越慢的问题。或许在js中,也只能如此的做监控了。如果读者知道有做js函数式响应监控的框架或demo,麻烦留言一下。嘿嘿。
转载于:https://my.oschina.net/myprogworld/blog/223524
AngularJS-源码阅读(八.二)相关推荐
- mybatis源码阅读(八) ---Interceptor了解一下
转载自 mybatis源码阅读(八) ---Interceptor了解一下 1 Intercetor MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,MyBatis允许 ...
- Alibaba Druid 源码阅读(二) 数据库连接池实现初步探索
Alibaba Druid 源码阅读(二) 数据库连接池实现初步探索 简介 在上篇文章中,了解了连接池的应用场景和本地运行了示例,本篇文章中,我们尝试来探索下Alibaba Druid数据库连接池的整 ...
- Soul 网关源码阅读(二)代码初步运行
Soul 源码阅读(二)代码初步运行 简介 基于上篇:Soul 源码阅读(一) 概览,这部分跑一下Soul网关的示例 过程记录 现在我们可以根据地图,稍微探索一下周边,摸一摸 ...
- Mybatis源码阅读之二——模板方法模式与Executor
[系列目录] Mybatis源码阅读之一--工厂模式与SqlSessionFactory 文章目录 一. 模板方法模式 二. 同步回调与匿名函数 三. Executor BaseExecutor与其子 ...
- gin context和官方context_gin 源码阅读(二) 路由和路由组
" 上一篇讲的是gin 框架的启动原理,今天来讲一下 gin 路由的实现. 1 用法 还是老样子,先从使用方式开始: func main() { r := gin.Default() r.G ...
- Rpc框架dubbo-client(v2.6.3) 源码阅读(二)
接上一篇 dubbo-server 之后,再来看一下 dubbo-client 是如何工作的. dubbo提供者服务示例, 其结构是这样的! dubbo://192.168.11.6:20880/co ...
- Lidar_imu自动标定源码阅读(二)——calibration部分
源码阅读,能力有限,如有某处理解错误,请指出,谢谢. Lidar_parser_base.h:激光雷达分析器基础 #pragma once#include <pcl/point_cloud.h& ...
- angularjs源码阅读-1-模块加载器
angularjs源码-setupModuleLoader 背景和开始 publishExternalAPI引入setupModuleLoader setupModuleLoader下面的逻辑 ens ...
- Kafka源码阅读-Controller(二)管理brokers
上一篇kafka源码(一)correspond to/explain Kafka设计解析(二) 中的3.2.3.3.以前一直用kafka 0.8.2.x,那时候redis开始风靡,hadoop方兴未艾 ...
- werkzeug源码阅读笔记(二) 下
wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...
最新文章
- C#设计模式(23种设计模式)
- Java01-day01【发展史、跨平台原理、JRE和JDK、常用DOS命令、关键字、常量、数据类型、变量使用的注意事项、标识符、类型转换】
- java上传文件到ftp_java实现文件上传下载至ftp服务器
- 博客园贵团队可以给个解释么?
- mysql 查看索引命中_请问下如何在Mysql中where与orderBy后在命中索引?
- java怎么获取ie浏览器的cookie,IE8 浏览器Cookie的处理
- 自学考试c语言真题,自学考试《C语言程序设计》复习试题及答案
- 关于matlab中get和set的用法
- 淘宝数据分析工具汇总
- Javascript:Ajax讲解
- 数据库悲观锁和乐观锁
- AifbdScore智能AI曲谱乐谱播放识别SDK midi曲谱 应用开发 五线谱 六线谱 四线谱播放
- https://mp.csdn.net/
- 异数OS 星星之火(一)-- 异数OS-织梦师云 用户使用手册
- 【Codecs系列】CABAC熵编码详解
- 组队开发最后冲刺周第三次会议
- 前缀编码是什么?哈夫曼编码是什么?
- omf多路径 oracle_ORACLE OMF
- C语言输出国际象棋的棋盘
- python爬取高匿代理IP(再也不用担心会进小黑屋了)