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

jquery1.83 之前所有與非同步列隊相關的模組詳細介紹_jquery

May 16, 2016 pm 05:48 PM

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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1248
24
JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在行動中:現實世界中的示例和項目 JavaScript在行動中:現實世界中的示例和項目 Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

See all articles