快捷搜索:

jQuery Callbacks详解

jQuery.Callbacks是jQuery的多用途核心组件,专职认真回调函数列队治理,其在jQuery的$.ajax() 和 $.Deferred()供给了一些根基功能。

其主要供给了易于治理的批量回调函数处置惩罚的功能。

说到批处置惩罚,在Javascript库中家常便饭:

Baidu七巧板有baidu.each()

Prototype有Enumerable#each

jQuery有.each()

等等…………

为了理解Callbacks函数的实现,我们先来懂得下jQuery.each()。

each()

我们可以在jQuery的源文件core.js找到其完备实现:

/奸淫奸淫奸淫奸淫奸淫奸淫奸淫

*obj: 行列步队列表*callback: 回调函数

*args: 回调函数的参数*/

jQuery.each = function( obj, callback, args ) {var value,

i = 0,length = obj.length,

isArray = isArraylike( obj );//obj是否是类Array工具

//假如有参数if ( args ) {

//假如obj是类Array工具if ( isArray ) {

for ( ; ivalue = callback.apply( obj[ i ], args );

if ( value === false ) {break;

}}

//否则} else {

for ( i in obj ) {value = callback.apply( obj[ i ], args );

if ( value === false ) {break;

}}

}//假如没有参数,则是一个更为常用的each函数

} else {if ( isArray ) {

for ( ; ivalue = callback.call( obj[ i ], i, obj[ i ] );

if ( value === false ) {break;

}}

} else {for ( i in obj ) {

value = callback.call( obj[ i ], i, obj[ i ] );if ( value === false ) {

break;}

}}

}

return obj; }

借助这个函数我们jQuery实现了其他each函数。如:

$( "li" ).each(function( index ) {console.log( index + ": "" + $(this).text() ); });

简略单纯Callbacks

实际上对简单的回调函数进行变形,我们也能弄成类似回调函数行列步队的效果:

function dosomething(__callbacks){//do something......

for(var i = __callbacks.length; i--;){__callbacks[i]();} }

例子:

function fn1( value ){

console.log( value );return false;

}

function fn2( value ){fn1("fn2 says:" + value);

return false; }

var callbacks = $.Callbacks( "unique memory" );

callbacks.add( fn1 ); callbacks.fire( "foo" );

callbacks.add( fn1 ); //重复添加 callbacks.add( fn2 );

callbacks.fire( "bar" ); callbacks.add( fn2 );

callbacks.fire( "baz" ); callbacks.remove( fn2 );

callbacks.fire( "foobar" );

/* output:

foo fn2 says:foo

bar fn2 says:bar

baz fn2 says:baz

foobar */

optionsCache

我们看到上面的例子中,flags参数因此字符串形式,每个参数以空格距离,如:

$.Callbacks( "unique memory" );

大年夜家会若何将字符串转成参数呢?

在这里Callbacks会经由过程正则表达式将字符串转数组,然后再组装成参数工具,如上面的例子,则着末参数工具是:

{unique: true,memory: true }

完备备注

jQuery.Callbacks = function( options ) {

//经由过程字符串在optionsCache探求有没有响应缓存,假如没有则创建一个,有则引用

//假如是工具则经由过程jQuery.extend深复制后赋给options。options = typeof options === "string" ?

( optionsCache[ options ] || createOptions( options ) ) :jQuery.extend( {}, options );

var // 着末一次触发还调时传的参数

memory,// 列表中的函数是否已经回调至少一次

fired,// 列表中的函数是否正在回调中

firing,// 回调的动身点

firingStart,// 回调时的轮回结尾

firingLength,// 当前正在回调的函数索引

firingIndex,// 回调函数列表

list = [],// 可重复的回调函数客栈,用于节制触发还调时的参数列表

stack = !options.once && [],// 触发还调函数列表

fire = function( data ) {//假如参数memory为true,则记录data

memory = options.memory && data;//标记触发还调

fired = true;firingIndex = firingStart || 0;

firingStart = 0;firingLength = list.length;

//标记正在触发还调firing = true;

for ( ; list && firingIndexif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {

memory = false; // 阻拦未来可能因为add所孕育发生的回调break;//因为参数stopOnFalse为true,以是当有回调函数返回值为false时退出轮回

}}

//标记回调停止firing = false;

//假如列表存在if ( list ) {

//假如客栈存在if ( stack ) {

//假如客栈不为空if ( stack.length ) {

//从客栈头部掏出,递归fire。fire( stack.shift() );

}//否则,假如有影象

} else if ( memory ) {//列表清空

list = [];//再否则阻拦回调列表中的回调

} else {self.disable();

}}

},// 裸露在外的Callbacks工具

self = {// 回调列表中添加一个回调或回调的聚拢。

add: function() {if ( list ) {

// 首先我们存储当前列表长度var start = list.length;

(function add( args ) {//前面我们看到的jQuery.each,对args传进来的列表的每一个工具履行操作

jQuery.each( args, function( _, arg ) {//获得arg的类型

var type = jQuery.type( arg );//假如是函数

if ( type === "function" ) {//确保是否可以重复

if ( !options.unique || !self.has( arg ) ) {list.push( arg );

}//假如是类数组或工具

} else if ( arg && arg.length && type !== "string" ) {//递归

add( arg );}

});})( arguments );

// 假如正在回调就将回调时的轮回结尾变成现有长度if ( firing ) {

firingLength = list.length;// 假如有memory,我们立即调用。

} else if ( memory ) {firingStart = start;

fire( memory );}

}return this;

},// 从列表删除回调函数

remove: function() {if ( list ) {

//继承用jQuery.each,对arguments中的所有参数处置惩罚jQuery.each( arguments, function( _, arg ) {

var index;//找到arg在列表中的位置

while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {//根据获得的位置删除列表中的回调函数

list.splice( index, 1 );//假如正在回调历程中,则调剂轮回的索引和长度

if ( firing ) {if ( index

firingLength--;}

if ( indexfiringIndex--;

}}

}});

}return this;

},// 回调函数是否在列表中

has: function( fn ) {return jQuery.inArray( fn, list ) > -1;

},// 从列表中删除所有回调函数

empty: function() {list = [];

return this;},

// 禁用回调列表中的回调。disable: function() {

list = stack = memory = undefined;return this;

},// 列表中否被禁用

disabled: function() {return !list;

},// 锁定列表

lock: function() {stack = undefined;

if ( !memory ) {self.disable();

}return this;

},// 列表是否被锁

locked: function() {return !stack;

},// 以给定的高低文和参数调用所有回调函数

fireWith: function( context, args ) {args = args || [];

args = [ context, args.slice ? args.slice() : args ];if ( list && ( !fired || stack ) ) {

//假如正在回调if ( firing ) {

//将参数推入客栈,等待当前回调停止再调用stack.push( args );

//否则直接调用} else {

fire( args );}

}return this;

},// 以给定的参数调用所有回调函数

fire: function() {self.fireWith( this, arguments );

return this;},

// 回调函数列表是否至少被调用一次fired: function() {

return !!fired;}

};

return self; };

您可能还会对下面的文章感兴趣: