jQuery.Callbacks()回調(diào)函數(shù)隊(duì)列用法詳解
本文實(shí)例講述了jQuery.Callbacks()回調(diào)函數(shù)隊(duì)列用法。分享給大家供大家參考,具體如下:
1、jQuery.Callbacks
The jQuery.Callbacks() function, introduced in version 1.7, returns a multi-purpose object that provides a powerful way to manage callback lists. It supports adding, removing, firing, and disabling callbacks.
The $.Callbacks() function is internally used to provide the base functionality behind the jQuery $.ajax() and $.Deferred() components. It can be used as a similar base to define functionality for new components.
接下來,我們分別看下四個(gè)標(biāo)準(zhǔn)的控制標(biāo)志。
1.1 once
創(chuàng)建的 callbacks 對象只允許被 fireWith() 一次 [注意:方法fire() 是 fireWith() 的外觀模式]。
var callbacks = $.Callbacks("once");
callbacks.add(function(){console.log("f1");});
callbacks.fire(); //輸出 "f1"
callbacks.fire(); //什么也不發(fā)生,在源碼中已經(jīng)禁用了 list.disable()
1.2 memory
在調(diào)用 add() 方法時(shí),如果這時(shí) callbacks隊(duì)列 滿足 fired && firing = false(真執(zhí)行完畢) && memory(需要在構(gòu)造函數(shù)指定),那么add() 進(jìn)去的回調(diào)函數(shù)會(huì)立即執(zhí)行,而這個(gè) add 進(jìn)去的回調(diào)函數(shù)調(diào)用時(shí)的參數(shù)存儲(chǔ)在 memory 變量中。memory 變量用于存儲(chǔ)最后一次調(diào)用 callbacks.fireWith(...) 時(shí)所使用的參數(shù) [context, arguments]。
If the Callbacks object is created with the "memory" flag as its argument, additional functions may be added and fired after the callback list is locked.
$(function($){
var callbacks = $.Callbacks("memory");
callbacks.add(function(){console.log("f1");});
callbacks.fire(); //輸出 "f1",這時(shí)函數(shù)列表已經(jīng)執(zhí)行完畢!
callbacks.add(function(){console.log("f2");}); //memory作用在這里,沒有fire,一樣有結(jié)果: f2
callbacks.fire(); //重新觸發(fā)一次,輸出 f1 f2。 firingStart = 0
//與once一起使用
callbacks = $.Callbacks("once memory");
callbacks.add(function(){console.log("f3");});
callbacks.fire(); //輸出 "f3",這時(shí)函數(shù)列表已經(jīng)執(zhí)行完畢!
callbacks.add(function(){console.log("f4");}); //沒有fire,一樣有結(jié)果: f4
callbacks.fire(); //由于為"once",這里將什么也不執(zhí)行
});
1.3 unique
回調(diào)函數(shù)列表中的函數(shù)是否可以重復(fù),該特性與 add() 方法有關(guān),可以避免在回調(diào)函數(shù)列表中加入多個(gè)相同回調(diào)函數(shù)。
var f1 = function(){console.log("f1");};
var callbacks = $.Callbacks();
callbacks.add(f1);
callbacks.add(f1);
callbacks.fire(); //輸出 f1 f1
//傳遞參數(shù) "unique"
callbacks = $.Callbacks("unique");
callbacks.add(f1); //有效
callbacks.add(f1); //添加不進(jìn)去
callbacks.fire(); //輸出: f1
1.4 stopOnFalse
默認(rèn)情況下,當(dāng)執(zhí)行 fireWith() 方法時(shí),整個(gè)回調(diào)函數(shù)列表中的所有函數(shù)都會(huì)順序執(zhí)行,但如果設(shè)置了stopOnFalse,那么當(dāng)某個(gè)函數(shù)返回false時(shí),后邊的函數(shù)將不再執(zhí)行。即使設(shè)置了memory,再次添加的函數(shù)也不會(huì)執(zhí)行了,即一旦某個(gè)函數(shù)返回 false 的情況下,會(huì)禁用 memory 功能。但如果沒設(shè)置”once”,再次調(diào)用fire可以重新觸發(fā)該callbacks。
var f1 = function(){console.log("f1"); return false}; //注意 return false;
var f2 = function(){console.log("f2");};
var callbacks = $.Callbacks();
callbacks.add(f1);
callbacks.add(f2);
callbacks.fire(); //輸出 f1 f2
callbacks = $.Callbacks("memory stopOnFalse");
callbacks.add(f1);
callbacks.add(f2);
callbacks.fire(); //只輸出 f1
callbacks.add(function(){console.log("f3");}); //不會(huì)輸出,memory已經(jīng)失去作用了
callbacks.fire(); //重新觸發(fā),輸出f1
2. memory 回調(diào)隊(duì)列
var i = 0;
var inc = function (s){
i++;
alert(i +"$" + s);
};
var callbacks = $.Callbacks('memory');
callbacks.add(function iteral() {
callbacks.add(inc);
if (i <= 1) {
callbacks.fire(i);
}
});
callbacks.fire(i);
callbacks.add(inc);
/*
list = [];
list = [it];
--->fire(0), i=0
1、list = [it, inc]
2、push(fire(0))
3、i++ [inc(0)] (i=1)
shift()--->fire(0), i=1
1、list = [it, inc, inc];
2、push(fire(1)),
3、i++ [inc(0)]
4、i++ [inc(0)] (i=3)
shift()--->fire(1),i=3
1、list = [it, inc, inc, inc];
2、i++ [inc(1)]
3、i++ [inc(1)]
4、i++ [inc(1)] (i=6)
--->add(inc), i=6, memory=[this,1]
1、i++ [inc(1)] (i=7)
*/
3、 jQuery.CallBacks 源碼
說明:為了便于理解,修改了部分源碼,減少了一些功能~~~
jQuery.Callbacks = function (options) {
// string --> object 改進(jìn)建議:將未配置的參數(shù)缺省為false,而不是undefined。便于程序閱讀和控制.
options = optionsCache[options] || createOptions(options);
var firing,
memory, //Last fire value [context, args] (for memory lists)
fired,
firingLength,
firingIndex,
firingStart,
list = [],
stack = options.once === true ? false : [], // Stack of fire calls for repeatable lists
fire = function (data) { // data --> [context, args]
memory = !!options.memory && data; // false OR [context, arguments]
fired = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
firing = true;
// 這里 list 放在條件判斷中是因?yàn)閳?zhí)行回調(diào)函數(shù)可能會(huì)改變 list 的狀態(tài),比如 this.disable()。
for ( ; list && firingIndex < firingLength; firingIndex++) {
if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse === true) {
memory = false; // 禁止 memory 功能,這樣調(diào)用 add() 增加新回調(diào)函數(shù)不會(huì)立即自動(dòng)調(diào)用
break;
}
}
firing = false;
if (list) {
if (stack) {
//進(jìn)入條件: fired && firing === false && stack, 實(shí)現(xiàn)遞歸調(diào)用
if (stack.length) {
fire(stack.shift()); // [[context1, arguments1], [context2, arguments2]]
}
} else if (memory) {
// 進(jìn)入條件: fired && firing === false && stack === undefined && 有memory字段(memory變量只能通過fire()函數(shù)修改)
// 這里的 list = [],主要是用于性能優(yōu)化,以防該對象長時(shí)間不執(zhí)行,占用系統(tǒng)內(nèi)存
list = [];
} else {
// 進(jìn)入條件: fired && firing === false && stack === undefined && 沒有memory字段, 說明必要繼續(xù)保留的必要
self.disable();
}
}
},
self = {
add: function() {
if (list) { //幾乎所有API都應(yīng)該綁定這個(gè)條件,因?yàn)槲覀冃枰幚黻?duì)列
var originLength = list.length;
jQuery.each(arguments, function( _, arg) {
if (jQuery.type(arg) === "function") {
// (!(options.unique && self.has(arg))) unique字段的作用
if (!options.unique || !self.has(arg)) {
list.push(arg);
}
}
});
if (firing === true) {
// 進(jìn)入條件: 說明正在執(zhí)行回調(diào)函數(shù)隊(duì)列中,而當(dāng)前執(zhí)行的這個(gè)回調(diào)函數(shù)激活了add()函數(shù),及時(shí)維護(hù)循環(huán)邊界
firingLength = list.length;
} else if (memory) {
// 進(jìn)入條件: memory && fired && firing === false, 說明之前的 fire() 行為已經(jīng)完全結(jié)束
firingStart = originLength;
fire(memory);
}
}
return this;
},
remove: function() {
if (list) {
jQuery.each(arguments, function( _, arg) {
var lastIndex;
while ((lastIndex = jQuery.inArray(arg, list, lastIndex)) >= 0) {
list.splice(lastIndex, 1);
if (firing === true) { // 及時(shí)更新邊界條件,實(shí)現(xiàn)智能處理
if (lastIndex <= firingLength) {
firingLength--;
}
if (lastIndex <= firingIndex) {
firingIndex--;
}
}
}
});
}
return this;
},
has: function (func) { //這個(gè)API有兩個(gè)功能,根據(jù)單一職責(zé)角度來說,應(yīng)該增加一個(gè) isNotEmpty() 接口(非空)
return func ? jQuery.inArray(func, list) > -1 : !!(list && list.length);
},
empty: function() {
list = [];
return this;
},
disable: function() { // 徹底禁用該對象, stack禁用, memory禁用
list = stack = memory = undefined;
return this;
},
disabled: function() {
return !list;
},
lock: function() {
stack = undefined;
// 如果memory沒有存儲(chǔ)調(diào)用狀態(tài),直接禁用這個(gè)對象(可能是從未調(diào)用就被鎖定,或者沒有memory字段)
if (!memory) {
self.disable();
}
return this;
},
locked: function() {
return !stack;
},
fireWith: function (context, args) {
args = args || [];
var data = [context, args];
if (list && (fired === false || stack) ) {
if (firing) {
// 進(jìn)入條件: firing === true && stack 說明當(dāng)前正在執(zhí)行回調(diào)函數(shù)隊(duì)列
stack.push(data); // stack其實(shí)是一個(gè)隊(duì)列結(jié)構(gòu),這里用 stack 有些混淆
} else {
// 進(jìn)入條件一: firing === false && fired === false 說明從來沒有 fire()過
// 進(jìn)入條件二: firing === false && fired === true && stack = [] 說明至少調(diào)用過一次,而且當(dāng)前允許多次調(diào)用,可以通過lock()鎖定
fire(args);
}
}
return this;
},
fire: function() {
self.fireWith(this, arguments);
return this;
},
fired: function() {
return !!fired;
}
};
return self;
};
4、胡思亂想
jQuery.Callbacks() 方法的核心是 fire() 方法,將該 fire() 方法被封裝在函數(shù)中不可直接訪問,因此像 memory、firing、fired 這些狀態(tài)對于外部上下文來說是不可更改的。
還有需要注意的是,如果回調(diào)函數(shù)中使用了 this 對象,可以直接用這個(gè) this 來訪問self對象的公有API。當(dāng)然,也可以用 fireWith() 自己指定 this 的引用對象。
jQuery.Callbacks()的核心思想是 Pub/Sub 模式,建立了程序間的松散耦合和高效通信。
更多關(guān)于jQuery相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《jQuery常用插件及用法總結(jié)》、《jquery中Ajax用法總結(jié)》、《jQuery表格(table)操作技巧匯總》、《jQuery拖拽特效與技巧總結(jié)》、《jQuery擴(kuò)展技巧總結(jié)》、《jQuery常見經(jīng)典特效匯總》、《jQuery動(dòng)畫與特效用法總結(jié)》及《jquery選擇器用法總結(jié)》
希望本文所述對大家jQuery程序設(shè)計(jì)有所幫助。
- jQuery回調(diào)函數(shù)的定義及用法實(shí)例
- jQuery 回調(diào)函數(shù)(callback)的使用和基礎(chǔ)
- 從零學(xué)jquery之如何使用回調(diào)函數(shù)
- jQuery AJAX回調(diào)函數(shù)this指向問題
- 淺談jquery回調(diào)函數(shù)callback的使用
- 一個(gè)超簡單的jQuery回調(diào)函數(shù)例子(分享)
- jQuery學(xué)習(xí)筆記之回調(diào)函數(shù)
- jQuery插件擴(kuò)展實(shí)例【添加回調(diào)函數(shù)】
- jQuery實(shí)現(xiàn)ajax回調(diào)函數(shù)帶入?yún)?shù)的方法示例
- jquery 回調(diào)操作實(shí)例分析【回調(diào)成功與回調(diào)失敗的情況】
相關(guān)文章
jQuery實(shí)現(xiàn)用戶注冊的表單驗(yàn)證示例
用戶注冊的表單往往是需要進(jìn)行驗(yàn)證的,否則會(huì)有一些不否合規(guī)則的數(shù)據(jù)入庫,后果會(huì)不堪設(shè)想,下面為大家詳細(xì)介紹下通過jquery是如何實(shí)現(xiàn)的,下面有個(gè)示例,感興趣的朋友可以參考下2013-08-08
jQuery實(shí)現(xiàn)的fixedMenu下拉菜單效果代碼
這篇文章主要介紹了jQuery實(shí)現(xiàn)的fixedMenu下拉菜單效果代碼,通過自定義fixedMenu方法實(shí)現(xiàn)點(diǎn)擊下拉菜單效果,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
jquery實(shí)現(xiàn)滑動(dòng)圖片自己測試的例子
最近使用jquery寫了一個(gè)圖片滑動(dòng)的插件,雖然還是有些問題存在,用法很簡單,希望對大家有所幫助2013-11-11
jquery中加載圖片自適應(yīng)大小主要實(shí)現(xiàn)代碼
當(dāng)圖片較小時(shí)顯示實(shí)際大小,當(dāng)圖片超過div 大小時(shí)圖片自動(dòng)適應(yīng)div的大小,下面有個(gè)示例,大家可以參考下,希望對大家有所幫助2013-08-08
jQuery簡單實(shí)現(xiàn)根據(jù)日期計(jì)算星期幾的方法
這篇文章主要介紹了jQuery簡單實(shí)現(xiàn)根據(jù)日期計(jì)算星期幾的方法,涉及jQuery針對日期時(shí)間簡單計(jì)算相關(guān)操作技巧,需要的朋友可以參考下2019-01-01
jQuery on()方法綁定動(dòng)態(tài)元素的點(diǎn)擊事件無響應(yīng)的解決辦法
這篇文章主要介紹了jQuery on()方法綁定動(dòng)態(tài)元素的點(diǎn)擊事件無響應(yīng)的解決辦法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07
jquery分析文本里url或郵件地址為真實(shí)鏈接的方法
這篇文章主要介紹了jquery分析文本里url或郵件地址為真實(shí)鏈接的方法,涉及jQuery正則匹配與替換的相關(guān)技巧,需要的朋友可以參考下2015-06-06
jQuery實(shí)現(xiàn)table中的tr上下移動(dòng)并保持序號(hào)不變的實(shí)例代碼
下面小編就為大家?guī)硪黄猨Query實(shí)現(xiàn)table中的tr上下移動(dòng)并保持序號(hào)不變的實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07

