前言
在js中使用回调函数是很常见的。但是当触发一个事件时需要同时执行多个回调函数时,我们可能就需要一个队列来把这些回调函数存放起来,当事件触发时按照队列的先进先出原则依次调用这些回调函数。在jQuery中就是使用$.Callbacks这个工具方法来管理回掉函数队列的。
1 function fn1(){ 2 console.log(1); 3 } 4 function fn2(){ 5 console.log(2); 6 } 7 var callbacks = $.Callbacks(); 8 callbacks.add(fn1); 9 callbacks.add(fn2); 10 callbacks.fire();// 1 2
当回调函数在不同的作用域也可以添加在一个队列中。
1 function fn1(){ 2 console.log(1); 3 } 4 var callbacks = $.Callbacks(); 5 !function(){ 6 function fn2(){ 7 console.log(2); 8 } 9 callbacks.add(fn2); 10 }(); 11 callbacks.add(fn1); 12 callbacks.fire();// 2 1
回调对象的方法
在jQuery源码中,所有的回调函数存在数组变量list中。
1、add:向list中添加回调函数。可以是一个或多个回掉函数参数,多个回掉函数也可以用数组的形式。
1 function fn1(){ 2 console.log(1); 3 } 4 function fn2(){ 5 console.log(2); 6 } 7 function fn3(){ 8 console.log(3); 9 } 10 var callbacks = $.Callbacks(); 11 callbacks.add(fn1); 12 callbacks.add(fn2); 13 callbacks.add(fn3); 14 callbacks.fire(); // 1 2 3
2、remove:从list中移除回调函数。可以是一个或多个回掉函数参数,多个回掉函数也可以用数组的形式。
1 callbacks.remove(fn1, fn2); 2 callbacks.fire(); // 3
3、has:无参数判断list中是否有回调函数,有参数判断该参数对应的回调函数是否在list中。
1 console.log(callbacks.has()); // true 2 console.log(callbacks.has(fn1)); // true
4、empty:清空回调对象的list。
5、disable:禁用回调对象,所有操作都不能执行。
6、disabled:判断回调对象是否被禁用。
7、lock:锁住,后面的fire和fireWith不能执行。
8、locked:判断是否是已被锁定的回调列表。
9、fireWith:
用法一:fireWith(执行上下文)
1 var name = 'window'; 2 var person = {name: 'hum'}; 3 function fn1(){ 4 console.log(this.name); 5 } 6 var callbacks = $.Callbacks(); 7 callbacks.add(fn1); 8 callbacks.fireWith(window); // window 9 callbacks.fireWith(person); // hum
用法二:fireWith(执行上下文,参数数组) 参数数组中的参数都会传递给每一个回调函数。
1 var name = 'window'; 2 var person = {name: 'hum'}; 3 function fn1(value){ 4 console.log(value + this.name); 5 } 6 function fn2(value1, value2){ 7 console.log(value1+ value2 + this.name); 8 } 9 var callbacks = $.Callbacks(); 10 callbacks.add(fn1); 11 callbacks.add(fn2); 12 callbacks.fireWith(window, ['window:', 'age:']); // window:window window:age:window 13 callbacks.fireWith(person, ['person:']); // person:hum person:undefinedhum
10、fire:fire方法调用了fireWith(this)方法,fireWith方法最终调用了源码中的fire私有函数
11、fired:判断回调列表是否已经被调用过(调用fire或fireWith方法)
回调对象的flag
$.Callbacks对象的flag决定了回调对象的类型。
1、once:只触发一次回调队列
1 function fn1(){ 2 console.log(1); 3 } 4 function fn2(){ 5 console.log(2); 6 } 7 var callbacks = $.Callbacks('once'); 8 callbacks.add(fn1); 9 callbacks.fire(); // 1 10 callbacks.add(fn2); 11 callbacks.fire(); // 不会触发
2、memory:记忆当次调用fire和fireWith,在遇到下次调用fire或fireWith之前,只要回调对象调用add方法都能执行,遇到下次调用时才会计算队列的remove、empty、add关系。
1 function fn1(){ 2 console.log(1); 3 } 4 function fn2(){ 5 console.log(2); 6 } 7 var callbacks = $.Callbacks('memory'); 8 callbacks.add(fn1); 9 callbacks.fire(); // 1 2 10 callbacks.add(fn2); 11 12 callbacks.fire(); // 1 2 2 13 callbacks.empty(); 14 callbacks.add(fn2); 15 16 callbacks.fire(); // 2 1 17 callbacks.add(fn1);
3、unique:去从。
1 function fn1(){ 2 console.log(1); 3 } 4 function fn2(){ 5 console.log(2); 6 } 7 var callbacks = $.Callbacks('unique'); 8 callbacks.add(fn1); 9 callbacks.add(fn2); 10 callbacks.add(fn2); 11 callbacks.fire(); // 1 2
4、stopOnFalse:当有一个对调函数返回false时,后面的回调都不会执行了。
1 function fn1(){ 2 console.log(1); 3 return false; 4 } 5 function fn2(){ 6 console.log(2); 7 } 8 var callbacks = $.Callbacks('stopOnFalse'); 9 callbacks.add(fn1); 10 callbacks.add(fn2); 11 callbacks.fire(); // 1
这四种类型可以组合使用,用空格隔开。
1 function fn1(){ 2 console.log(1); 3 return false; 4 } 5 function fn2(){ 6 console.log(2); 7 } 8 var callbacks = $.Callbacks('once memory'); 9 callbacks.fire(); 10 callbacks.add(fn1); // 1 2 11 callbacks.add(fn2); 12 callbacks.fire(); // 没有输出