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