JQuery日记6.9 Promise/A之Callbacks
注:不解的是走到stack.push分支时是在回调函数里调用fire或fireWidth,但这样会导致死循环,这个stack究竟怎么回事?还请明确的同学告知我一下。!
jQuery.Callbacks = function( options ) {
// Convert options from String-formatted to Object-formatted if needed
// (we check in cache first)
options = typeof options === "string" ?
( optionsCache[ options ] || createOptions( options ) ) :
jQuery.extend( {}, options );
var // Last fire value (for non-forgettable lists)
memory,
// Flag to know if list was already fired
fired,
// Flag to know if list is currently firing
firing,
// First callback to fire (used internally by add and fireWith)
firingStart,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingIndex,
// Actual callback list
list = [],
// Stack of fire calls for repeatable lists
// 假设没有配置once,stack为数组
// stack存放反复时fire參数
stack = !options.once && [],
// Fire callbacks
fire = function( data ) {
//memory 为false或fire时传入的參数
memory = options.memory && data;
fired = true;
//当前触发位置
firingIndex = firingStart || 0;
//触发回调函数队列的起始位置
firingStart = 0;
//待触发的回调函数队列长度
firingLength = list.length;
//正在触发标识设置为true
//仅仅有在Callbacks的回调函数里此值才会为true
firing = true;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
//若配置了stopOnFalse当回调函数队列中函数返回值为false
if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
//memory设置为false
memory = false; // To prevent further calls using add
//不再运行后面的回调函数
break;
}
}
//回调函数运行结束
firing = false;
if ( list ) {
//未配置once
if ( stack ) {
//运行在回调函数里调用的fire
if ( stack.length ) {
fire( stack.shift() );
}
//清空回调函数列表,但此callbacks仍可用
} else if ( memory ) {
list = [];
//让闭包的那些引用能够销毁
} else {
self.disable();
}
}
},
// Actual Callbacks object
self = {
// Add a callback or a collection of callbacks to the list
add: function() {
if ( list ) {
// First, we save the current length
// 将加入回调函数之前将当前callbacks的长度设为运行開始
var start = list.length;
( function add( args ) {
jQuery.each( args, function( _, arg ) {
var type = jQuery.type( arg );
if ( type === "function" ) {
// 假设未设置unique或者回调函数列表里没有此函数
// 在回调函数队列里加上此函数
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
// 假设arg是个类数组,再递归add
} else if ( arg && arg.length && type !== "string" ) {
// Inspect recursively
add( arg );
}
});
})( arguments );
// Do we need to add the callbacks to the
// current firing batch?
//在正在触发的回调函数中调用add方法会走此分支
if ( firing ) {
//立马反应要触发回调函数长度的改变
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away
} else if ( memory ) {
//改变触发的開始位置为未加入前的回调队列长度
firingStart = start;
fire( memory );
}
}
return this;
},
// Remove a callback from the list
remove: function() {
if ( list ) {
jQuery.each( arguments, function( _, arg ) {
//arg所在list的索引
var index;
while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
//删除
list.splice( index, 1 );
// Handle firing indexes
//假设在回调函数里调用remove
if ( firing ) {
//要删除的回调函数是还没触发的
if ( index <= firingLength ) {
//触发的长度减一
firingLength--;
}
//要删除的是已经触发过的函数
if ( index <= firingIndex ) {
//正要触发索引减一
firingIndex--;
}
}
}
});
}
return this;
},
// Check if a given callback is in the list.
// If no argument is given, return whether or not list has callbacks attached.
has: function( fn ) {
return fn ?
jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
},
// Remove all callbacks from the list
empty: function() {
list = [];
firingLength = 0;
return this;
},
// Have the list do nothing anymore
//是回调函数列表功能全然失效
disable: function() {
list = stack = memory = undefined;
return this;
},
// Is it disabled?
disabled: function() {
return !list;
},
// Lock the list in its current state
//锁住当前的状态,不会运行在回调函数里调用fire或fireWidth
lock: function() {
stack = undefined;
if ( ! memory ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
//没有被触发或者能够反复触发
if ( list && ( !fired || stack ) ) {
args = args || [];
args = [ context, args.slice ? args.slice() : args ];
//?事实上这里有一点不解,走到这个分
//是在在回调函数里调通fire或fireWidth,但这样会导致死循环
if ( firing ) {
stack.push( args );
} else {
fire( args );
}
}
return this;
},
// Call all the callbacks with the given arguments
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
fired: function() {
return !!fired;
}
};
return self;
};
JQuery日记6.9 Promise/A之Callbacks的更多相关文章
- javascript异步代码的回调地狱以及JQuery.deferred提供的promise解决方式
我们先来看一下编写AJAX编码常常遇到的几个问题: 1.因为AJAX是异步的,全部依赖AJAX返回结果的代码必需写在AJAX回调函数中.这就不可避免地形成了嵌套.ajax等异步操作越多,嵌套层次就会越 ...
- jquery源码分析(四)——回调对象 Callbacks
借用百度百科来说明下回调函数: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该 ...
- JQuery日记6.7 Javascript异步模型(二)
异步模型看起来非常美,但事实上它也是有天生缺陷的.看以下代码 try { setTimeout( function(){ throw new Error( '你抓不到我的!' ); }, 100); ...
- JQuery日记_5.13 Sizzle选择器(六)选择器的效率
当选择表达式不符合高速匹配(id,tag,class)和原生QSA不可用或返回错误时,将调用select(selector, context, results, seed)方法,此方法迭代DO ...
- JQuery日记6.5 Javascript异步模式(一)
理解力JQuery前实现异步队列,有必要理解javascript异步模式. Javascript异步其实并不严重格异步感,js使某些片段异步方式在将来运行,流不必等待继续向下进行. 在多线程的语言中最 ...
- JQuery日记 5.11 Sizzle选择器(五)
//设置当前document和document相应的变量和方法 setDocument = Sizzle.setDocument = function( node ) { var hasCompare ...
- JQuery日记 5.31 JQuery对象的生成
JQuery对象的生成 1 selector为不论什么可转换false的空值 返回空JQuery对象 2 selector为字符串 2.1 selector为html字符串或有id属性的标签 ...
- JQuery日记_5.14 Sizzle选择器(七)
上篇说道,tokenize方法会把selector切割成一个个selector逻辑单元(如div>a是三个逻辑单元 'div','>','a')并为之片段赋予相应类型的过滤函数. for ...
- Jquery AJAX如何使用Promise/Deferred实现顺序执行?
有的时候有我有N个AJAX请求,第下个请求可能要依赖上个请求的返回值, 可以用 $.ajax("test1.php").then(function(data) { // data ...
随机推荐
- (Inno setup打包)检测系统是否已安装程序,若已安装则弹出卸载提示的代码
原文 http://bbs.itiankong.com/thread-30983-1-5.html 有6天没研究pascal代码了,昨天晚上突然来了灵感,终于解决了苦思冥想好几天没能解决的问题, 因此 ...
- Matalab之模糊KMeans原理
对Kmeans方法相信大家都会不陌生,这是一种广泛被应用的基于划分的聚类算法.首先对它的核心思想做一个简单的介绍: 算法把n个向量xj(1,2…,n)分为c个组Gi(i=1,2,…,c),并求每组的聚 ...
- cf468A 24 Game
A. 24 Game time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- poj1163 dp入门
The Triangle Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 36811 Accepted: 22048 De ...
- SVN连接不上
某次我们部门换了场地.SVNserver就连接不上了,后来公司数据中心处理好后,还是连接不上,原来还需刷新自己电脑的DNS. 如需转载,请注明出处http://blog.csdn.net/combat ...
- poj 2186 (强连通缩点)
题意:有N只奶牛,奶牛有自己认为最受欢迎的奶牛.奶牛们的这种“认为”是单向可传递的,当A认为B最受欢迎(B不一定认为A最受欢迎),且B认为C最受欢迎时,A一定也认为C最受欢迎.现在给出M对这样的“认为 ...
- Android的Bitmap和BitmapDrawable类解析-android学习之旅(六十)
使用简单图片 使用Drawable对象 bitmap和BitmapDrawable对象 package peng.liu.test; import android.app.Activity; impo ...
- JDK自带工具jps,jstat,jmap,jconsole使用
jps 与ps命令类似: ps -ef|grep java 用来显示本地的java进程,查看本地执行着几个java应用,并显示进程号. [root@SE43 ~]# jps //仅仅显示进程号 238 ...
- 【最大团】【HDU1530】【Maximum Clique】
先上最大团定义: 最大团问题(Maximum Clique Problem, MCP)是图论中一个经典的组合优化问题,也是一类NP完全问题,在国际上已有广泛的研究,而国内对MCP问题的研究则还处于起步 ...
- 字符串对比.net String.EndsWith方法 (String)
string str="web/abc.aspx"; if(str.EndsWith("abc.aspx")) { 此方法将 value 与位于此实例末尾.与 ...