天天看點

jQuery源碼分析系列(38) : 隊列操作

Queue隊列,如同data資料緩存與Deferred異步模型一樣,都是jQuery庫的内部實作的基礎設施

Queue隊列是animate動畫依賴的基礎設施,整個jQuery中隊列僅供給動畫使用

Queue隊列

隊列是一種特殊的線性表,隻允許在表的前端(隊頭)進行删除操作(出隊),在表的後端(隊尾)進行插入操作(入隊)。隊列的特點是先進先出(FIFO-first in first out),即最先插入的元素最先被删除。

為什麼要引入隊列?

我們知道代碼的執行流有異步與同步之分,例如

<a></a>

我們一直習慣于“線性”地編寫代碼邏輯,但是在JavaScript程式設計幾乎總是伴随着異步操作:

setTimeout,CSS3 Transition/Animation,ajax,dom的繪制,postmessage,Web Database等等,大量異步操作所帶來的回調函數,會把我們的算法分解地支離破碎

之前我們說過對于異步+回調的模式,怎麼“拉平”異步操作,使之跟同步一樣,因為異步操作進行流程控制的時候無非避免的要嵌套大量的回調邏輯,是以就會出現promises約定了

那麼jQuery引入隊列其實從一個角度上可以認為:允許一系列函數被異步地調用而不會阻塞程式

這是jQuery的一組動畫鍊式序列,它的内部其實就是一組隊列Queue,是以隊列和Deferred地位類似, 是一個内部使用的基礎設施,當slideUp運作時,fadeIn被放到fx隊列中,當slideUp完成後,從隊列中被取出運作。queue函數允許 直接操作這個鍊式調用的行為。同時,queue可以指定隊列名稱獲得其他能力,而不局限于fx隊列

jQuery提供了2組隊列操作的API:

jQuery.queue/dequeue

jQuery.fn.queue/dequeue

但是不同與普通隊列定義的是:jQuery.queue和jQuery.fn.queue不僅執行出隊操作,傳回隊頭元素,還會自動執行傳回的隊頭元素

fn是擴充在原型上的進階API是提供給執行個體使用的,.queue/.dequeue, 其内部是調用的.queue,.queue,.dequeue靜态的底層方法實作入列與出列

$.queue : 顯示或操作比對的元素上已經執行的函數列隊

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

這個方法有點類型get有點類似隊列的push操作,jQuery的方法的接口重載是非常嚴重的,經常同一個接口即是set也是get,不管符不符合基本原則,但是它卻很實用

無非就是把資料給緩存起來,為什麼載體是一個jQuery對象,因為儲存資料的手段是通過data資料緩存實作的

源碼有一個預設處理

type = (type || "fx") + "queue"

可見是專職供fx動畫隊列處理的

$.dequeue : 比對的元素上執行隊列中的下一個函數

出列就有點類似shift的操作,但是不同的是還會執行這個cb1與cb2

将回調函數出列執行,每調用一次僅出列一個,是以當回調有N個時,需要調用$.dequeue方法N次元素才全部出列

來看看源碼:

知道原理了, 這個就很簡單了,通過queue的get取出隊列的所有資料,判斷一下長度,然後截取出第一個,然後做好一個預處理生成下一個的next

這裡有一個hooks?

仔細分析下這個内部queueHooks

我們說了dequeue不僅是取出來還需要執行,在執行的時候把next與hooks傳遞給外部的回調,

這就是js的邏輯上的很繞的地方,在内部可以傳遞一個引用出去,又能提供外部調用或者執行

因為傳遞了next,是以我們的代碼可以這樣改

next内部仍然調用$.dequeue,這樣可以接着執行隊列中的下一個callback

$.dequeue裡的hooks是當隊列裡所有的callback都執行完後(此時startLength為0)進行最後的一個清理工作

鈎子其實就是jQuery.Callbacks對象,可以實作一個收集器的功能,至于在什麼情況下時候,之後動畫中開始分析

是以隊列的本質是利用Array的push和shift來完成先進先出(First In First Out),但是這個方法的缺點也很明顯,無法單獨做一個獨立的子產品處理,因為它必須要跟jQuery對象吻合,而且對傳遞的資料隻能是函數

本文轉自艾倫 Aaron部落格園部落格,原文連結:http://www.cnblogs.com/aaronjs/p/3800619.html,如需轉載請自行聯系原作者

繼續閱讀