JavaScript實現一個Promise隊列小工具
摘要
在百度的解釋中,隊列是一種特殊的線性表,特殊之處在于它只允許在表的前端進行刪除操作,而在表的后端進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。
受這個隊列結構的啟發(fā),在前端不同的業(yè)務場景中,由于一次性發(fā)起的異步請求過多,并且這些服務位于不同組件或者不同兄弟功能之間,我們無法直接對這些方法進行同步,所以需要引入隊列的概念,對這些并發(fā)性的問題進行順序處理。
思考
為什么要寫一個類似于隊列的功能?
我們知道,在主流的V8引擎中,JavaScript 的執(zhí)行順序都是至上而下的,引入了 ajax 之后我們能夠對網頁進行局部刷新,在前端領域第一次有了異步操作的概念。自此,當我們接觸 Promise 之后也不在陌生于這種模式。當然,使用過 Promise 的都知道,如果是在某個單一的 js 文件中,我們完全可以通過編寫一個 async 函數,通過使用 await 去實現將 Promise 函數按順序執(zhí)行的功能。
那這個隊列小工具難道就是無意義的嗎?作者就像一個大渣男,玩弄了一番感情輕飄飄的走了?當然不是,大家都知道在單一文件中,我們總有辦法去實現這樣控制異步操作的功能,那么在不同的模塊、組件中,如何去實現這樣的操作呢?按照這個思路,我們可以發(fā)現單純的去寫是沒辦法直接解決這樣的異步功能同時觸發(fā)的問題的,這也就是作者為什么要去些一個類似于隊列的功能。
Promise 隊列功能的思路在哪里?
我們先要搞明白我們想要的是一個怎樣的功能呢?作者畫了一個大概的需要實現功能的流程圖,我們不同組件的異步請求是同時發(fā)生的,我們需要在發(fā)生之前把Promise 函數放入隊列工具,再讓隊列工具去調度出棧和入棧的順序,每次出棧的時候再去調用 Promise 函數發(fā)生請求。

我們可以在 js 文件中使用一個單例的概覽,主要是記錄入棧的順序和對操作加鎖,并且啟動一個定時服務去定期檢測棧中是否還有順序,思路是很簡單的,說干就干。
實現
我們新建一個 useQueue.js 文件,為了方便后續(xù)的引用。首先我們需要定義三個高級變量:
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
}這個時候,我們在單例上設置一個心跳來定期檢測加鎖狀態(tài),如果是解鎖則觸發(fā)處理函數。
// 心跳
setInterval(() => {
locks && handler()
}, 100)當函數 hander 被成果觸發(fā),我們需要設置一個延時器來處理防抖。先進行加鎖,然后在隊列中進行出棧,如果出棧為空則解鎖;如果出棧不為空則調用任務,并且等待任務結束進入下一個 hander 。
const handler = () => {
timer && clearTimeout(timer)
timer = setTimeout(() => {
locks = false
const task = queue.shift()
if (task) {
task().then(handler)
} else {
locks = true
}
})
}假設我們已經寫了一個 vue 字典標簽組件,組件內部會調用遠程接口,并且再記錄到某一個緩存中。如果一個頁面多次使用組件,而該緩存還并未存在,那么可能會導致同時觸發(fā)多個異步網絡請求。這個時候就可以使用隊列工具。
import useQueue from './useQueue.js'
const handleAjax = () => {
return new Promise(resolve => {
...
resolve()
})
}
useQueue(handleAjax)
// 或者可以這樣調用
useQueue(async () => {
await handleAjax()
})總結
Promise 隊列工具實際上是通過延遲觸發(fā),來處理掛載在某一隊列數據上的出棧任務,原理其實并不復雜,就是為了處理異步請求同時發(fā)生的情況。當然,這個函數可以有更多的優(yōu)化方案,比如說可以添加一個優(yōu)先級的參數值,根據不同優(yōu)先級進行入棧操作,或者增加一個同類型排異等等。
到此這篇關于JavaScript實現一個Promise隊列小工具的文章就介紹到這了,更多相關JS Promise隊列內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
小程序開發(fā)實戰(zhàn):實現九宮格界面的導航的代碼實現
本篇文章主要介紹了小程序開發(fā)實戰(zhàn):實現九宮格界面的導航的代碼實現,具有一定的參考價值,有興趣的可以了解一下。2017-01-01
微信小程序 image組件binderror使用例子與js中的onerror區(qū)別
這篇文章主要介紹了微信小程序 image組件binderror使用例子與js中的onerror區(qū)別的相關資料,需要的朋友可以參考下2017-02-02
Project?Reference優(yōu)化TypeScript編譯性能示例
這篇文章主要為大家介紹了Project?Reference優(yōu)化TypeScript編譯性能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08
微信小程序組件 contact-button(客服會話按鈕)詳解及實例代碼
這篇文章主要介紹了微信小程序組件 contact-button(客服會話按鈕)詳解及實例代碼的相關資料,需要的朋友可以參考下2017-01-01

