搜尋
首頁web前端js教程jquery1.83 之前所有與非同步列隊相關的模組詳細介紹_jquery

jQuery在1.5引入了Deferred对象(异步列队),当时它还没有划分为一个模块,放到核心模块中。直到1.52才分割出来。它拥有三个方法:_Deferred, Deferred与when。

出于变量在不同作用域的共用,jQuery实现异步列队时不使用面向对象方式,它把_Deferred当作一个工厂方法,返回一个不透明的函数列队。之所以说不透明,是因为它的状态与元素都以闭包手段保护起来,只能通过列队对象提供的方法进行操作。这几个方法分别是done(添加函数),resolveWith(指定作用域地执行所有函数),resolve(执行所有函数),isResolved(判定是否已经调用过resolveWith或resolve方法),cancel(中断执行操作)。但_Deferred自始至终都作为一个内部方法,从没有在文档中公开过。

Deferred在1.5是两个_Deferred的合体,但1+1不等于2,它还是做了增强。偷偷爆料,Deferred本来是python世界大名鼎鼎的Twisted框架的东西,由早期七大JS类库中的MochiKit取经回来,最后被dojo继承衣钵。jQuery之所以这样构造Deferred,分明不愿背抄袭的恶名,于是方法改得一塌糊涂,是jQuery命名最差的API,完全不知所云。它还加入当时正在热烈讨论的promise机制。下面是一个比较列表:

dojo jQuery 注解
addBoth then 同时添加正常回调与错误回调
addCallback done 添加正常回调
addErrback fail 添加错误回调
callback done 执行所有正常回调
errback reject 执行所有错误回调
doneWith 在指定作用域下执行所有正常回调,但dojo已经在addCallback上指定好了
rejectWith 在指定作用域下执行所有错误回调,但dojo已经在addErrback上指定好了
promise 返回一个外界不能改变其状态的Deferred对象(外称为Promise对象)

jQuery的when方法用於實現回調的回調,或者說,幾個異列列隊都執行後才執行另外的一些回調。這些後來的回調也是用done, when, fail加的,但when回傳的這個物件已經加入讓使用者控制它執行的能力了。因為這時它是種叫Promise的東西,只負責增加回呼與讓使用者窺探其狀態。一旦前一段回呼都觸發了,它就自然進入正常回調列隊(deferred ,見Deferred方法的定義)或錯誤回調列隊(failDeferred )中去。不過我這樣講,對於沒有非同步程式設計經驗的人來說,一定聽得雲裡霧裡。看實例好了。
複製程式碼 程式碼如下:

$.when({aa:1},, {aa :2}).done(function(a,b){
console.log(a.aa)
console.log(b.aa)
});

直接輸出1,2。如果是傳入兩個函數,也是傳回兩個函數。因此對於普通的資料型,前面的when有多少個參數,後面的done, fail方法的回呼就有多少個參數。
複製程式碼 程式碼如下:

function fn(){


function fn(){
return 4; 🎜>}
function log(s){
window.console && console.log(s)
}
$.when( { num:1 }, 2, '3', fn( ) ).done(function(o1, o2, o3, o4){
log(o1.num);
log(o2);
log(o3);
log(o4);
});

如果我們想得到各個非同步的結果,我們需要用resolve, resolveWith, reject, rejectWith進行傳遞它們。 複製程式碼
程式碼如下:


var log = function(msg){
window .console && console.log(msg)
}
function asyncThing1(){
var dfd = $.Deferred();
setTimeout(function(){
log('asyncning1 to be done...');
dfd.resolve('1111');
},1000);
return dfd.promise();
}
function asyncThing2() {
var dfd = $.Deferred();
setTimeout(function(){
log('asyncThing2 seems to be done...');
dfd.resolve('222') ;
},1500);
return dfd.promise();
}
function asyncThing3(){
var dfd = $.Deferred();
setTimeout(function( ){
log('asyncThing3 seems to be done...');
dfd.resolve('333');
},2000);
return dfd.promise();
}
/* do it */
$.when( asyncThing1(), asyncThing2(), asyncThing3() ).done(function(res1, res2, res3){
('all done!');
log(res1 ', ' res2 ', ' res3);
})

異步列隊一開始沒什麼人用(現在也沒什麼人用,概念太抽象了,方法名起得太爛了),於是它只能在內部自產自銷。首先被染指的是queue。 queue模組是1.4為吸引社群的delay插件,特地從data模組分化的產物,而data則是從event模組化分出來的。 jQuery新模組的誕生總是因為使用者對已有API的局限制不滿而致。最早的queue模組的原始碼: 複製程式碼
程式碼如下:

jQuery.extend({
queue: function( elem, type, data ) {
if ( !elem ) {
return;
}
type = (type || "fx") "queue";
var q = jQuery.data( elem, type ); // 如果只是查找,則可以快速出隊
if ( !data ) {
return q
}
if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray( data) );
} else {
q.push(
}
回傳q;
},
出隊: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ), fn = queue.shift(); // 如果fx 隊列出隊,則始終移除進度哨兵
if ( fn === "inprogress" ) {
fn = queue.shift();
if ( fn ) {
// 增加進度哨兵以防止fx 隊列
// 自動出隊
if ( type === "fx" ) {
queue.unshift("inprogress");
}
fn.call(elem, function( ) {
jQuery.dequeue(elem, type)
});
jQuery .fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = " fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function( i , elem ) {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery .dequeue(this this , type );
}
});
出隊: function( type ) {
return this.each(function() {
jQuery. dequeue( this, type );
});
// 基於Clint Helfers 的插件,經許可。 php/2009/07/jquery-delay/
延遲:函數( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;類型|| "fx ";
回傳this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
},時間);
});
clearQueue: function( type ) {
return this.queue( type || "fx", [] ); >}
});


1.6 增加了_mark,_unmark,promise。 queue 是讓函數同屬一個隊伍裡面,目的是讓動畫一個接一個執行。 _mark 頂讓他們各自擁有隊伍,並列執行(雖然其中只記錄非同步列隊中已被執行的函數個數)。 promise則在這些並發執行的動畫執行後才執行另外一些回呼(或動畫)。




複製程式碼


程式碼如下:

(function( jQuery ) {
function handleQueueMarkDefer( elem, type, src ) {
//清空記錄deferredvar個數的隊字段,函數列隊與異步列
type "defer",
queueDataKey = type "queue",
markDataKey = type "mark",
defer = jQuery.data( elem, deferDataKey, undefined, true );
if ( defer &&
( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
( src === "mark" || !jQuery.data( elem, markDataKey, undefined , true ) ) ) {
// 為硬編碼回調提供空間,以便先觸發
// 並最終在元素上標記/排隊其他內容
setTimeout( function() {
if 。 );
}
}, 0
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = (type || "fx") "mark";//建立一個以mark為後綴的字段,用於記錄此列隊中的個數
jQuery.data( elem, type, (jQuery.data (elem,類型,未定義,true) || 0) 1, 正確);
}
},
_unmark: function(force, elem, type ) {
if (force != = true ) {
type = elem;
elem = 力;
力=假;
}
if ( elem ) {
type = type || “fx”;
var key = type "mark",
//讓個數減1,如果第一個參數為true,就強逼減至0
count = force ? 0 : ( (jQuery.data( elem , key, 未定義, true) || 1 ) - 1 );
if ( count ) {
jQuery.data( elem, key, count, true );
} else {//如果為0,就移除它
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
},
隊列: function( elem, type, data ) {
if ( elem ) {
type = (type || "fx") "queue 」;
var q = jQuery.data( elem, type, undefined, true );
// 如果這只是一個查找,則透過快速退出來加速出隊
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery.資料( elem, 類型, jQuery.makeArray(data), true );
} else {
q.push( 資料);
}
}
回傳q || [];
}
},
出隊: function( elem, type ) {
type = type || “fx”;
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
defer;
// 如果fx 隊伍列出隊,總是刪除進度標記
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// 增加進度哨兵,防止fx 佇列被
// 自動出列
if ( type === "fx" ) {
queue.unshift("進行中");
}
fn.call(elem, function() {
jQuery.dequeue(elem, type );
});
}
if ( !queue.length ) {
jQuery.removeData( elem, type "queue", true );
handleQueueMarkDefer( elem, type, " queue" );
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = " fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function() {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue [0] !== "inprogress" ) {
jQuery.dequeue(這個,類型);
}
});
出隊:函數( type ) {
回傳this. each(function() {
jQuery.dequeue( this , type );
},
// 基於Clint Helfers 的插件,經許可。 /07/jquery-delay/
延遲:函數( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; "fx";
return this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
}, 時間);
},
clearQueue: function( type ) {
return this.queue( type || "fx",
},
//把jQuery 物件裝進一個非同步列隊,允許它在一步列隊,允許它在一步列隊系列動畫中再執行之後綁定的回呼
promise: function( type, object ) {
if ( typeof type !== "字串" ) {
物件= 類型;
類型=未定義;
}
類型= 類型|| “fx”;
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type "defer",
queueDataKey =輸入“佇列”,
markDataKey = 輸入“標記”;
函數resolve() {
if ( !( - -count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
//如果之前已經使用過unmark、queue等方法,那麼我們將產生一個新的延遲感測器硬碟系統
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data( elements[ i ],queueDataKey, undefined, true ) ||
jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferData, jQuery._Deferred( true ) )) {
count ;
tmp.done( 解決);
}
}
resolve();
回傳defer.promise();
}
});
})( jQuery );

jQuery.ajax模組也被染指,$.XHR對象,當作HTTPXMLRequest對象的仿造器是由一個Deferred對象與一個_Deferred的對象構成。
複製程式碼 程式碼如下:

deferred = jferred.Deferred( = jQuery._Deferred(),
jqXHR ={/**/}
//....
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqXHR.error = jqXHR.fail;
jqXHR.complete = completeDeferred.done;

jQuery1.7,從deferred模組中分化出callback模組,其實就是先前的_Deferred的增強版,新增去重,鎖定,return false時中斷執行下一個回調,清空等功能。

複製程式碼 程式碼如下:

(function( jQuery ) {
// 字串到物件標誌格式快取
var flagsCache = {};
// 將字串格式的標誌轉換為物件格式的標誌並且儲存在快取
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /s / ) i = 0, length = flags.length; i
object[ flags[i] ] = true;
傳回物件;
* 使用下列參數建立回呼清單:
*
* 標誌:以空格分隔的標誌的可選列表,將更改
* 回調列表的行為方式
*
* 預設情況下,回調列表將像事件回調列表一樣,並且可以
*“觸發”多次
*
* 可能的標誌:
*
*一次:將確保回呼列表只能被觸發一次(如延遲)
*
* 內存:將跟踪以前的值,並在列表立即觸發後調用任何添加的回調
* 最新的“記憶”
*值(如延遲)
*
*唯一:將確保回調只能添加一次(清單中沒有重複)
*
* stopOnFalse:中斷呼叫當回調回傳false
*
*/
jQuery.Callbacks = function( flags ) {
// 將標誌從字串格式轉換為物件格式
// (我們簽入先快取)
flags = flags ? ( flagsCache[ 標誌] || createFlags( 標誌) ) : {};
var // 實際回呼列表
list = [],
// 可重複列表的fire 呼叫堆疊
stack = [],
// 最後的fire 值(用於不可忘記的) list)
memory,
// 標記以了解清單目前是否正在觸發
firing,
// 第一個觸發回調(由add 和fireWith 內部使用)
firingStart,
// 觸發時循環結束
firingLength,
// 目前觸發回調的索引(如果需要,可透過刪除進行修改)
firingIndex,
// 將一個或多個回調加入清單
add = function( args ) {
var i,
長度,
elem,
類型,
實際;
for ( i = 0, length = args.length; i
for ( i = 0, length = args.length; i elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// 遞歸檢查
add( elem );
} else if ( type === "function" ) {
// 增加if 不是唯一模式且回呼不在
if ( !flags.unique || !self.has ( elem ) ) {
list.push( elem );
}
}
}
},
// 觸發回呼
fire = function( context, args ) {
args = args || [];
內存= !flags.內存|| [上下文,參數];
開火= true;
fireingIndex = fireStart || 0;
點火開始= 0;
fireingLength = list.length;
for ( ; list &&fireingIndex if (list[fireingIndex].apply( context, args ) = flagsse & flags ) = flags, args ) = flagse & flags ) = flags args ) = flags ) stopOnFalse ) {
內存= true; // 標記為停止
break;
}
}
開火= false;
if ( list ) {
if ( !flags>if ( !flags>if ( !flags>if !flags .once ) {
if ( stack && stack.length ) {
內存= stack.shift();
self.fireWith( 內存[ 0 ], 內存[ 1 ] );
}
} else if (內存=== true ) {
self.disable();
} else {
list = [];
}
}
},
// 實際回呼物件
self = {
// 將回呼或回呼集合新增至清單
add: function( ) {
if ( list ) {
var length = list .length;
新增(參數);
// 我們是否需要將回調新增至
// 目前觸發批次?
if (fireing) {
firingLength = list.length;
// 有了內存,如果我們沒有開火,那麼
// 我們應該立即調用,除非之前的
//開火被停止(stopOnFalse)
} else if ( memory && memory ! == true ) {
firingStart = 長度;
火(記憶體[0],記憶體[1]);
}
火(記憶體[0],記憶體[1]);
}
火(記憶體[0],記憶體[1]); 🎜>}
傳回此;
},
// 從清單中刪除回呼
remove: function() {
if (list ) {
var args = arguments,
argIndex = 0,
argLength = args.length;
for ( ; argIndex for ( var i = 0; i { <.length if args argindex list i>// 處理firingIndex 和firingLength
if (firing ) {
if ( i firingLength--;
if ( i fireingIndex--;
}
}
}
//刪除元素
list.splice( i--, 1 ) ;
// 如果我們有一些唯一性屬性,那麼
// 我們只需要執行一次
if ( flags.unique ) {
break;
}
}
}
}
}
回傳此;
},
// 控制給定回呼是否在列表中
has: function( fn ) {
if (list ) {
var i = 0,
length =列表長度;
for ( ; i if ( fn === list[ i ] ) {
返回true;
}
}
}
回傳false;
},
// 從清單中移除所有回呼
empty: function() {
list = [];
回傳這個;
},
// 讓清單不再執行任何動作
disable: function() {
list = stack = memory = undefined;
回傳這個;
},
//是否禁用?
停用:function() {
return !list;
},
// 將清單鎖定在目前狀態
lock: function() {
stack = undefined;
if ( !內存|| 內存=== true ) {
self.disable();
}
返回此;
},
//是否已鎖定?
鎖定: function() {
return !stack;
},
// 使用給定的上下文和參數呼叫所有回呼
fireWith: function( context, args ) {
if ( stack ) {
if (fireing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, args );
}
}
傳回此;
},
// 使用給定參數呼叫所有回呼
fire: function() {
self.fireWith( this,arguments );
回傳這個;
},
// 了解回呼是否已被呼叫至少一次
fired : function() {
return !!memory;
}
};
回自我;
};
})( jQuery );

})( jQuery );
複製程式碼


如下程式碼:


(function( jQuery ) {
{},
sliceTopic = [].slice;
jQuery.Topic = function( id ) {
var 回呼,
方法,
topic = id && 主題[ id ]; topic ) {
callbacks = jQuery.Callbacks()
topic = {
發布:callbacks.fire,
訂閱:callbacks.add,
取消訂閱:callbacks.remove
} ; 🎜>if ( id ) {
topics[ id ] = topic;
}
返回主題
}
jQuery.extend({
訂閱: function( id ) {
var topic = jQuery.Topic( id ),
args = sliceTopic.call(args, 1 );
topic.subscribe.apply( topic, args ); return {
主題:主題,主題:主題,args
};
取消訂閱:函數( id ) {
var topic = id && id.topic || jQuery.主題( id );
topic.unsubscribe.apply( topic, id && id.args ||
sliceTopic.call( 參數, 1 ) );
},
發佈: 函數( id ) {
var topic = jQuery.Topic( id );
topic.publish.apply( topic, sliceTopic.call(arguments, 1 ) );
}
});
})( jQuery );

雖然把大量程式碼移動回調,但1.7的Deferred卻一點沒變小,它變得更重型,由三個函數列隊組成了。而回傳的是Promise對象,比原來多長了pipe, state,progress,always方法。 ajax端變成這樣:

複製程式碼 程式碼如下:
deferredred = jQuery.Deferred (),
completeDeferred = jQuery.Callbacks( "一次記憶體" ),
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqqHR.eror =
jqXHR.complete =completeDeferred.add;

隊列兩邊也變了多少。

複製程式碼程式碼如下:

(function( jQuery ) {
function handleQueueMarkDefer( elem, type, src ) {
var deferDataKey = type "defer",
queue🎜>var deferDataKey = type "defer",
queue🎜>var deferDataKey = type "defer",
= type "mark",
defer = jQuery._data( elem, deferDataKey );
if ( defer &&
( src === "queue" || !jQuery._data(Keyelem, queueData) ) ; &&
( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
// 為硬編碼回調提供空間,首先觸發
// 最後標記/在元素上排隊其他內容
setTimeout( function() {
if ( !jQuery._data( elem,queueDataKey ) &&
!jQuery._data( elem, markDataKey ) ) {
!jQuery._data( elem, markDataKey ) ) {
jQuery.removeKey ) ) {
jQuery.removeKey ) ) {
jQuery.removeKey ) ) {
jQuery.removeKey ( elem, deferDataKey, true );
defer.fire()
}
}, 0 );
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = ( type || "fx" ) "mark";
jQuery._data( elem, type, (jQuery._data( elem,型) || 0) 1 );
}
},
_unmark: function(force, elem, type ) {
if (force !== true ) {
type = elem ;
元素=力
力=假;
}
if ( elem ) {
type = type || “fx”;
var key = 輸入“mark”,
count = 力? else {
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
: function( elem, type, data ) {
var q;
if ( elem ) {
type = ( type || "fx" ) "queue";
q = jQuery._data( elem, 類型);
// 如果這只是一個查找,則透過快速退出來加速出隊
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery. _data( elem, 類型, jQuery.makeArray(data) );
} else {
q.push( 資料);
}
}
回傳q || [] ;
}
},
出隊: function( elem, type ) {
type = type || “fx”;
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
hooks = {};
// 如果fx 隊伍列出隊,總是刪除進度標記
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// 增加進度哨兵,防止fx 佇列被
// 自動出列
if ( type === "fx" ) {
queue.unshift(“進行中”);
}
jQuery._data( elem, type ".run", hooks );
fn.call( elem, function() {
jQuery.dequeue( elem, type );
}, hooks );
}
if ( !queue.length ) {
jQuery.removeData(elemqueue.length ) {
jQuery.removeData(elemem, type "queue " type ".run", true );
handleQueueMarkDefer( elem, type, "queue" );
}
}
});
jQuery.fn.extend( {
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx ";
setter --
}
if (args.length return jQuery.queue( this[0], type ) ;
}
回傳資料= == 未定義
this :
this.each(function() {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
});
出隊: function( type ) {
return this .each(function() {
jQuery.dequeue( this, type );
});
},
//基於Clint Helfers 的插件,經許可
// http: //blindsignals.com/index.php/2009/07/jquery-delay/
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx"; {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout )
}); 🎜>clearQueue: function( type ) {
return this.queue( type || “fx”,[]);
},
// 當某種類型的隊列被清空時,得到一個已解決的Promise
// (fx 是預設型別)
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
類型=未定義;
}
類型= 類型|| “fx”;
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type "defer",
queueDataKey =輸入“佇列”,
markDataKey = 輸入“標記”,
tmp
;函數resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data ( elements[ i ],queueDataKey, undefined, true ) ||
>jery .data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery. Callbacks( "一次記憶" ), true ) )) {
count ;
tmp.add( 解析);
}
}
resolve();
回傳defer.promise( 物件);
}
});
} )( jQuery );


這時候,鉤子機制其實已經在jQuery內部蔓延起來,1.5是css模組的cssHooks,1.6是屬性模組的attrHooks, propHooks, boolHooks, nodeHooks,1.7是事件模組的fixHooks, keyHooks, mouseHooks,1.模組的_queueHooks,由於_queueHooks,queue終於瘦身了。
複製程式碼 程式碼如下:

View Code?/1.8


View Code?/1.8
jery.ext ({
queue: function( elem, type, data ) {
var queue;
if ( elem ) {
type = ( type || "fx" ) "queue";
queue = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
if ( !queue ||Query.isray(3( data) ) {
queue = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
queue.push( data );
}
}
}
return queue || [];
}
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery. queue( elem, type ),
fn = queue.shift(),
hooks = jQuery._queueHooks( elem, type ),
next = function() {
jQuery.dequeue( elem, type );
};
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
// clear up the last queue stop function
delete hooks.stop;
fn.call( elem, next
}
if ( !queue.length && hooks ) {
hooks.empty.fire();
}
},
// not intended for public consumption - generates a queueH object, 或 returns the current one
_queueHooks: function( elem, type ) {
var key = type "queueHooks";
return jQuery._data( elem, key key) || Query. key, {
empty: jQuery.Callbacks("once memory").add(function() {
jQuery.removeData( elem, type "queue", true );
jQuery.removeData( elem, key, true );
})
});
}
});
jQuery.fn.extend({
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx";
s--;
}
}
if ( arguments.length return jQuery.queue( this[0], type );
}
return data === undefined ?
this :
return data === undefined ?
this :
this. each(function() {
var queue = jQuery.queue( this, type, data );
// ensure a hooks for this queue
jQuery._queueHooks( this, type );
jQuery._queueHooks( this, type );
if
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
});
},
dequeue: function( type ) {
return this.each(function() {
jQuery.dequeue( this, type );
});
},
// Based off of the plugin by Clint Helfers, with permission.
// http://blindsignals.com/index.php/2009/07/jquery-delay/
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout );
};
});
}
}; clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// Get a promise resolved when queues of a certain type
/ / are emptied (fx is the type by default)
promise: function( type, obj ) {
var tmp,
count = 1,
defer = jQuery.Deferred(>count = 1,
defer = jQuery.Deferred(), 🎜> elements = this,
i = this.length,
resolve = function() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
};
if ( typeof type !== "string" ) {
obj = type;
type = undefined;
}
type = type || " fx";
while( i-- ) {
if ( (tmp = jQuery._data( elements[ i ], type "queueHooks" )) && tmp.empty ) {
count ;
tmp.empty.add( resolve );
} 同時,動畫模組迎來了它第三次大重構,它也有一個鉤子Tween.propHooks。它多出兩個對象,其中Animation返回一個非同步列隊,Tween 是用於處理單一樣式或屬性的變化,相當於之前Fx對象。 animate被抽空了,它在1.72可是近百行的規模。 jQuery透過鉤子機制與分化出一些新的對象,將一些巨型方法重建。現在非常長的方法只龜縮在節點模組,回呼模組。 複製程式碼 程式碼如下:

animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ), doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall ) ;
// Empty animations resolve immediately
if ( empty ) {
anim.stop( );
}
};
return empty || optall.queue = ||== false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
},

到目前為止,所有異步的東西都被jQuery改造成非同步列隊的「子類」或叫「變種」比較合適些。如domReady, 動畫,AJAX,與執行了promise或delay或各種特效方法之後的jQuery物件。於是所有非同步的東西在promise的加護下,像同步那樣寫非同步程式。
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在JavaScript中替換字符串字符在JavaScript中替換字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

自定義Google搜索API設置教程自定義Google搜索API設置教程Mar 04, 2025 am 01:06 AM

本教程向您展示瞭如何將自定義的Google搜索API集成到您的博客或網站中,提供了比標準WordPress主題搜索功能更精緻的搜索體驗。 令人驚訝的是簡單!您將能夠將搜索限制為Y

示例顏色json文件示例顏色json文件Mar 03, 2025 am 12:35 AM

本文系列在2017年中期進行了最新信息和新示例。 在此JSON示例中,我們將研究如何使用JSON格式將簡單值存儲在文件中。 使用鍵值對符號,我們可以存儲任何類型的

構建您自己的Ajax Web應用程序構建您自己的Ajax Web應用程序Mar 09, 2025 am 12:11 AM

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

8令人驚嘆的jQuery頁面佈局插件8令人驚嘆的jQuery頁面佈局插件Mar 06, 2025 am 12:48 AM

利用輕鬆的網頁佈局:8 ESTISSEL插件jQuery大大簡化了網頁佈局。 本文重點介紹了簡化該過程的八個功能強大的JQuery插件,對於手動網站創建特別有用

什麼是這個&#x27;在JavaScript?什麼是這個&#x27;在JavaScript?Mar 04, 2025 am 01:15 AM

核心要點 JavaScript 中的 this 通常指代“擁有”該方法的對象,但具體取決於函數的調用方式。 沒有當前對象時,this 指代全局對象。在 Web 瀏覽器中,它由 window 表示。 調用函數時,this 保持全局對象;但調用對象構造函數或其任何方法時,this 指代對象的實例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。這些方法使用給定的 this 值和參數調用函數。 JavaScript 是一門優秀的編程語言。幾年前,這句話可

通過來源查看器提高您的jQuery知識通過來源查看器提高您的jQuery知識Mar 05, 2025 am 12:54 AM

jQuery是一個很棒的JavaScript框架。但是,與任何圖書館一樣,有時有必要在引擎蓋下發現發生了什麼。也許是因為您正在追踪一個錯誤,或者只是對jQuery如何實現特定UI感到好奇

10張移動秘籍用於移動開發10張移動秘籍用於移動開發Mar 05, 2025 am 12:43 AM

該帖子編寫了有用的作弊表,參考指南,快速食譜以及用於Android,BlackBerry和iPhone應用程序開發的代碼片段。 沒有開發人員應該沒有他們! 觸摸手勢參考指南(PDF)是Desig的寶貴資源

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
1 個月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)