這篇“怎么用JavaScript實現一個Promise隊列小工具”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么用JavaScript實現一個Promise隊列小工具”文章吧。
為什么要寫一個類似于隊列的功能?
我們知道,在主流的V8引擎中,JavaScript
的執行順序都是至上而下的,引入了 ajax
之后我們能夠對網頁進行局部刷新,在前端領域第一次有了異步操作的概念。自此,當我們接觸 Promise
之后也不在陌生于這種模式。當然,使用過 Promise
的都知道,如果是在某個單一的 js
文件中,我們完全可以通過編寫一個 async
函數,通過使用 await
去實現將 Promise
函數按順序執行的功能。
那這個隊列小工具難道就是無意義的嗎?作者就像一個大渣男,玩弄了一番感情輕飄飄的走了?當然不是,大家都知道在單一文件中,我們總有辦法去實現這樣控制異步操作的功能,那么在不同的模塊、組件中,如何去實現這樣的操作呢?按照這個思路,我們可以發現單純的去寫是沒辦法直接解決這樣的異步功能同時觸發的問題的,這也就是作者為什么要去些一個類似于隊列的功能。
Promise
隊列功能的思路在哪里?
我們先要搞明白我們想要的是一個怎樣的功能呢?作者畫了一個大概的需要實現功能的流程圖,我們不同組件的異步請求是同時發生的,我們需要在發生之前把Promise
函數放入隊列工具,再讓隊列工具去調度出棧和入棧的順序,每次出棧的時候再去調用 Promise
函數發生請求。
我們可以在 js
文件中使用一個單例的概覽,主要是記錄入棧的順序和對操作加鎖,并且啟動一個定時服務去定期檢測棧中是否還有順序,思路是很簡單的,說干就干。
我們新建一個 useQueue.js
文件,為了方便后續的引用。首先我們需要定義三個高級變量:
var queue = [] var locks = false var timer = null
queue
:記錄入棧的 Promise
任務函數
locks
:在處理出棧任務時我們需要對函數加鎖,防止多次出棧
timer
:防抖記錄,跟功能 locks
主要起一個保險左右,防止出棧時重復調用函數
我們定義兩個函數 hander
、useQueue
,導出默認函數 useQueue
。
/** * 處理任務出棧 */ const hander = () => {} /** * 入棧等待排隊操作 * @param {Promise} task */ const useQueue = (task) => {} /** * 導出 */ export default useQueue
當我們有任務進入時,啟用 useQueue
函數,將任務放入棧中,并且設置 locks = true
進行解鎖。
const useQueue = (task) => { queue.push(task) locks = true }
這個時候,我們在單例上設置一個心跳來定期檢測加鎖狀態,如果是解鎖則觸發處理函數。
// 心跳 setInterval(() => { locks && handler() }, 100)
當函數 hander
被成果觸發,我們需要設置一個延時器來處理防抖。先進行加鎖,然后在隊列中進行出棧,如果出棧為空則解鎖;如果出棧不為空則調用任務,并且等待任務結束進入下一個 hander
。
const handler = () => { timer && clearTimeout(timer) timer = setTimeout(() => { locks = false const task = queue.shift() if (task) { task().then(handler) } else { locks = true } }) }
假設我們已經寫了一個 vue
字典標簽組件,組件內部會調用遠程接口,并且再記錄到某一個緩存中。如果一個頁面多次使用組件,而該緩存還并未存在,那么可能會導致同時觸發多個異步網絡請求。這個時候就可以使用隊列工具。
import useQueue from './useQueue.js' const handleAjax = () => { return new Promise(resolve => { ... resolve() }) } useQueue(handleAjax) // 或者可以這樣調用 useQueue(async () => { await handleAjax() })
以上就是關于“怎么用JavaScript實現一個Promise隊列小工具”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。