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ù)存儲在 memory 變量中。memory 變量用于存儲最后一次調(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沒有存儲調(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 Validate表單驗(yàn)證插件 添加class屬性形式的校驗(yàn)
這篇文章主要介紹了jQuery Validate表單驗(yàn)證插件,在class屬性中添加校驗(yàn)規(guī)則進(jìn)行簡單的校驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01jquery實(shí)現(xiàn)聯(lián)想詞搜索框和搜索結(jié)果分頁的示例
今天小編就為大家分享一篇jquery實(shí)現(xiàn)聯(lián)想詞搜索框和搜索結(jié)果分頁的示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10jquery實(shí)現(xiàn)的鼠標(biāo)下拉滾動(dòng)置頂效果
鼠標(biāo)下拉滾動(dòng)置頂效果想必大家在瀏覽網(wǎng)頁時(shí)都有遇到過,下面有個(gè)不錯(cuò)的小例子,需要的朋友可以參考下2014-07-07使用jQuery時(shí)Form表單元素ID和name命名大忌
將自己的表單元素ID和name命名為了nodeName,在chrome瀏覽器下報(bào)錯(cuò),結(jié)果發(fā)現(xiàn)是表單元素命名的原因2014-03-03基于jquery實(shí)現(xiàn)二級聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了基于jquery二級聯(lián)動(dòng)效果的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03解決Jquery鼠標(biāo)經(jīng)過不停滑動(dòng)的問題
在鼠標(biāo)經(jīng)過的時(shí)候不停的顯示隱藏html元素,正確的寫法應(yīng)該是下面這樣的,需要的朋友可以參考下2014-03-03javascript jQuery $.post $.ajax用法
這是一個(gè)簡單的 POST 請求功能以取代復(fù)雜 $.ajax 。請求成功時(shí)可調(diào)用回調(diào)函數(shù)。如果需要在出錯(cuò)時(shí)執(zhí)行函數(shù),請使用 $.ajax。2008-07-07jQuery學(xué)習(xí)筆記(3)--用jquery(插件)實(shí)現(xiàn)多選項(xiàng)卡功能
多選項(xiàng)卡功能的網(wǎng)站有很多,本人在那么多的類似插件中,目前碰到這個(gè)比較好,花了點(diǎn)時(shí)間調(diào)試出來了與大家分享,感興趣的朋友可以參考下哈希望對你有所幫助2013-04-04