异步队列用于实现异步任务和回调函数的解耦,为ajax模块、队列模块、ready事件提供基础功能,包含三个部分:Query.Callbacks(flags)、jQuery.Deferred(funct)和jQuery.when()。本节讲解Callbacks,也就是回调函数列表
回调函数用于管理一组回调函数,支持添加、移除、触发、锁定和禁用回调函数,为jQuery.ajax、jQuery.Deferred()和ready()事件提供基础功能,我们也可以基于它编写新的组件。
使用方法:$.Callbacks(flags),flags是一个参数,用于指定传递的标记,可以为空,可以设置为以下四个选项之一,或者任意组合也可以,如下:
unique 确保一个回调函数只能被添加一次
stopOnFlase 当某个回调函数返回false时中断执行
once 确保回调函数列表只能被触发一次
memory 记录上一次触发回调函数列表时的参数,之后添加的任何函数都将用记录的参数值立即调用
执行成功后返回一个对象,该函数含有如下几个方法:
add(fn/arr) 添加一个/多个回调函数到list数组中
remove(fn1,fn2,fn3...) 从list中移除多个回调函数
empty() 清空list数组
disable() 禁用列表,使他不再做任何事情,该操作不可还原
disabled() 判断是否已禁用列表,如果已经禁用了则返回true
lock() 锁定memory模式下的回调函数的上下文和参数
locked() 判断回调函数列表是否已被锁定
fireWith(content,args) 以content为上下文,args为上下文,执行所有函数列表
fire(arguments) 指定上下文为当前回调函数列表来调用fireWith
fired() 通过检测变量memory的值来判断回调函数列表是否被触发过
这些方法归纳起来就是新增/移除/触发回调函数,还有几个是查看当前的状态的(是否已触发、是否被禁用等)
$.Callbacks()可以传入任意组合,也可以为空,例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script> </head> <body> <script> function fn1(val){console.log('fn1 says:' + val);} function fn2(val){console.log('fn2 says ' + val);} function fn3(val){console.log('fn3 says ' + val);} var cbs = $.Callbacks(); //创建Callbacks对象 cbs.add([fn1,fn2,fn3]); //添加函数到回调函数列表中 cbs.fire('test1'); //触发回调函数,参数是test1 输出:fn1 says:test1、fn2 says:test1和fn3 says:test cbs.remove(fn1,fn3); //移除回调函数fn1,fn3 cbs.fire('test2'); //触发回调函数,输出:fn2 says test2 </script> </body> </html>
输出如下:
这里我们定义了一个Callback(),没有传入任何参数,比较常用的是once和memory的组合,例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script> </head> <body> <script> function fn1(val){console.log('fn1 says:' + val);} function fn2(val){console.log('fn2 says ' + val);} function fn3(val){console.log('fn3 says ' + val);} var cbs = $.Callbacks('once memory'); cbs.add([fn1,fn2]); cbs.fire('test'); //输出:fn1 says:test和fn2 says:test cbs.fire('test'); //没有输出,因为设置了once标志,当调用cbs.fire('test')后就把list清空了 cbs.add(fn3); </script> </body> </html>
输出如下:
如果传入once+memory的组合,这时回调函数被触发后再调用fire()去触发时是不会执行回调函数了的,因为当第一次fire()触发回调函数后,如果由once标记就把内部的list设为了undefined,可以理解为把list给禁用了,加入了memory标记的话当执行fire()时jQuery内部会把当时的上下文和参数保存起来,这样下次直接添加回调函数就会自动回掉函数了
源码分析
writer by:大沙漠 QQ:22969969
$.Callbacks()的实现原理很简单,Callbacks是jQuery内部的一个函数,第一次执行时该函数会把传入的标记给缓存起来,通过作用域保存在内部的一个变量中,之后调用add()添加函数时也会一个个的缓存起来,最后调用fire()触发回调函数时会遍历这些回调函数列表,一个个的去触发,中间根据不同的标记做不同的处理。
$.Callbacks是直接定义在内部的jQuery上的,大致如下
jQuery.Callbacks = function