讀jQuery之二十一(隊列queue)

來源:互聯網
上載者:User

queue模組在jQuery中分在Effects中,搜尋整個庫會發現queue也僅在特效模組effects.js中被使用。jQuery抽取出獨立的命名空間給queue,說明除了內部Effects模組使用外,用戶端程式員可以充分發揮聰明才智使用queue來構建非動畫API。

queue模組向外開放的API分別是

  • 掛在$上的$.queue、$.dequeue、$._queueHooks(僅內部)
  • 掛在jQuery對象上的有queue、dequeue、delay、clearQueue、promise

 

按照jQuery的慣例,掛在$上的方法屬於低級API,掛在jQuery對象上的才是經常使用的。

一般低級API是為進階API服務的,即 queue內部會使用$.queue, dequeue內部會使用$.dequeue。這裡實際是實現為一個隊列,$.queue是入列,$.dequeue是出列。

 

一、$.queue

這個方法有兩個作用,它既是setter,又是getter。第一個參數elem是DOM元素,第二個參數type是字串,第三個參數data可以是function或數組。

1. 設定指定名字的queue

function cb1() {alert(1)}function cb2() {alert(2)}var arr = [cb1, cb2];$.queue(el, 'mx', cb1); // 第三個參數為function$.queue(el, 'xm', arr); // 第三個參數為數組

 

2. 這時可以取到存入的callbacks

var cbs1 = $.queue(el, 'mx'); // [cb1]var cbs2 = $.queue(el, 'xm'); // [cb1, cb2]

 

$.queue內部使用 $._data方法,將資料儲存下來。預設type/queueName使用  "fx" + queue。$.queue的實現很簡單,代碼不過15行,即取緩衝對象queue,如果不存在則初始化為一個Null 物件,然後將data存入,如果存在則直接將data push到數組中。

 

二、$.dequeue 

將回呼函數出列執行,每調用一次僅出列一個,因此當回調有N個時,需要調用$.dequeue方法N次元素才全部出列。$.dequeue的第一個參數是dom元素,第二個參數是queueName

function ff1() {console.log(1)}function ff2() {console.log(2)}function ff3() {console.log(3)}var p = $('p')[0];$.queue(p, 'mx1', ff1);$.queue(p, 'mx1', ff2);$.queue(p, 'mx1', ff3);// 每2秒調用一次$.dequeue,依次輸出1,2,3setInterval(function() {$.dequeue(p, 'mx1') }, 2000);

 回呼函數的上下文是dom元素,參數是next函數和hooks對象

var p = $('p')[0];function func(next, hooks) {   console.log(this);   console.log(next);   console.log(hooks);}$.queue(p, 'mx', func);$.dequeue(p, 'mx'); // p, function, [object Object]

 

next內部仍然調用$.dequeue,這樣可以接著執行隊列中的下一個callback。$.dequeue裡的hooks是當隊列裡所有的callback都執行完後(此時startLength為0)進行最後的一個清理工作,

if ( !startLength && hooks ) {hooks.empty.fire();}

hooks.empty是一個jQuery.Callbacks對象,而它則是定義在$._queueHooks裡

_queueHooks: function( elem, type ) {var key = type + "queueHooks";return jQuery._data( elem, key ) || jQuery._data( elem, key, {empty: jQuery.Callbacks("once memory").add(function() {jQuery._removeData( elem, type + "queue" );jQuery._removeData( elem, key );})});}

 

以上就是queue的全部了,本質是利用Array的push和shift來完成先進先出(First In First Out),但這裡有個缺陷,jQuery的queue從1.1開始就是為effects模組服務的,因此queue裡存的都是function。個人覺得如果只存function,應該對data參數做個嚴格類型判斷,如果不是function則拋異常。但目前的版本沒有做嚴格判斷,如果我存的不是function,這樣dequeue時會報錯。如下

var p = $('p')[0];$.queue(p, 'mx1', {}); // 注意第三個參數是對象,非function$.dequeue(p, 'mx1'); // fn.call 報錯,因為fn不是function

 

三、queue

知道了$.queue,queue就很好理解了,它無非是內部調用了下$.queue。queue比$.queue 少了第一個參數,內部使用this代替第一個參數。

function ff1() {console.log(1)}function ff2() {console.log(2)}function ff3() {console.log(3)}var $p = $('p');$p.queue('mx', ff1);$p.queue('mx', ff2);$p.queue('mx', ff3);

這樣,三個function就入列了,列名是"mx"。 取隊列元素只需傳一個列名如"mx"

var queue = $p.queue('mx'); // [ff1, ff2, ff3]

 

還有個技巧就是,如果使用jQuery預設的隊列"fx",可以只傳data

function ff1() {console.log(1)}function ff2() {console.log(2)}function ff3() {console.log(3)}var $p = $('p');$p.queue(ff1);$p.queue(ff2);$p.queue(ff3);

另外一點,當使用預設列名"fx"時,它會調用$.dequeue出列執行下,源碼如下

if ( type === "fx" && queue[0] !== "inprogress" ) {jQuery.dequeue( this, type );}

 

四、dequeue

dequeue則更是未添加任何特殊處理,直接調用的$.dequeue,見源碼

dequeue: function( type ) {return this.each(function() {jQuery.dequeue( this, type );});},

 

五、delay

delay用來延遲後續添加的callback的執行,第一個參數time是延遲時間(另可使用"slow"和"fast"),第二個是隊列名。

function cb() {    console.log(1);    }var $p = $('p');$p.delay(2000, 'mx').queue('mx', cb); $p.dequeue('mx'); // 2秒後輸出1

如果是這樣

function ff1() {console.log(1)}function ff2() {console.log(2)}var $p = $('p');$p.queue('mx', ff1);$p.delay(4000, 'mx');$p.queue('mx', ff2);$p.dequeue('mx'); // 立即輸出1$p.dequeue('mx'); // 4秒後輸出2

 

六、clearQueue

顧名思義,清空所有隊列。沒什麼好說的,源碼如下,直接使用一個空數組覆蓋之前的數組隊列了。

clearQueue: function( type ) {return this.queue( type || "fx", [] );},

  

七、promise

這個方法返回一個promise對象,promise對象既是前面提到的Deferred對象的閹割版。你可以使用done、fail、progress添加,但不能觸發。用在queue模組裡有特殊意義,比如done它指queue裡所有function都執行後才執行done添加的。如

function ff1() {alert(1)}function ff2() {alert(2)}function succ() {alert('done')}$body = $('body')$body.queue('mx', ff1);$body.queue('mx', ff2);var promise = $body.promise('mx');promise.done(succ);setInterval(function() {$body.dequeue('mx') // 先彈出1,2,最後是"done"}, 1500)

 

註:閱讀版本為1.9.1

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.