欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript實(shí)現(xiàn)一個(gè)Promise隊(duì)列小工具

 更新時(shí)間:2022年09月01日 14:47:04   作者:小樹(shù)ZW???????  
這篇文章主要介紹了JavaScript實(shí)現(xiàn)一個(gè)Promise隊(duì)列小工具,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

摘要

在百度的解釋中,隊(duì)列是一種特殊的線性表,特殊之處在于它只允許在表的前端進(jìn)行刪除操作,而在表的后端進(jìn)行插入操作,和棧一樣,隊(duì)列是一種操作受限制的線性表。進(jìn)行插入操作的端稱為隊(duì)尾,進(jìn)行刪除操作的端稱為隊(duì)頭。

受這個(gè)隊(duì)列結(jié)構(gòu)的啟發(fā),在前端不同的業(yè)務(wù)場(chǎng)景中,由于一次性發(fā)起的異步請(qǐng)求過(guò)多,并且這些服務(wù)位于不同組件或者不同兄弟功能之間,我們無(wú)法直接對(duì)這些方法進(jìn)行同步,所以需要引入隊(duì)列的概念,對(duì)這些并發(fā)性的問(wèn)題進(jìn)行順序處理。

思考

為什么要寫一個(gè)類似于隊(duì)列的功能?

我們知道,在主流的V8引擎中,JavaScript 的執(zhí)行順序都是至上而下的,引入了 ajax 之后我們能夠?qū)W(wǎng)頁(yè)進(jìn)行局部刷新,在前端領(lǐng)域第一次有了異步操作的概念。自此,當(dāng)我們接觸 Promise 之后也不在陌生于這種模式。當(dāng)然,使用過(guò) Promise 的都知道,如果是在某個(gè)單一的 js 文件中,我們完全可以通過(guò)編寫一個(gè) async 函數(shù),通過(guò)使用 await 去實(shí)現(xiàn)將 Promise 函數(shù)按順序執(zhí)行的功能。

那這個(gè)隊(duì)列小工具難道就是無(wú)意義的嗎?作者就像一個(gè)大渣男,玩弄了一番感情輕飄飄的走了?當(dāng)然不是,大家都知道在單一文件中,我們總有辦法去實(shí)現(xiàn)這樣控制異步操作的功能,那么在不同的模塊、組件中,如何去實(shí)現(xiàn)這樣的操作呢?按照這個(gè)思路,我們可以發(fā)現(xiàn)單純的去寫是沒(méi)辦法直接解決這樣的異步功能同時(shí)觸發(fā)的問(wèn)題的,這也就是作者為什么要去些一個(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)單的,說(shuō)干就干。

實(shí)現(xià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ù) handeruseQueue,導(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è)心跳來(lái)定期檢測(cè)加鎖狀態(tài),如果是解鎖則觸發(fā)處理函數(shù)。

// 心跳
setInterval(() => {
  locks && handler()
}, 100)

當(dāng)函數(shù) hander 被成果觸發(fā),我們需要設(shè)置一個(gè)延時(shí)器來(lái)處理防抖。先進(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è)頁(yè)面多次使用組件,而該緩存還并未存在,那么可能會(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()
})

總結(jié)

Promise 隊(duì)列工具實(shí)際上是通過(guò)延遲觸發(fā),來(lái)處理掛載在某一隊(duì)列數(shù)據(jù)上的出棧任務(wù),原理其實(shí)并不復(fù)雜,就是為了處理異步請(qǐng)求同時(shí)發(fā)生的情況。當(dāng)然,這個(gè)函數(shù)可以有更多的優(yōu)化方案,比如說(shuō)可以添加一個(gè)優(yōu)先級(jí)的參數(shù)值,根據(jù)不同優(yōu)先級(jí)進(jìn)行入棧操作,或者增加一個(gè)同類型排異等等。

到此這篇關(guān)于JavaScript實(shí)現(xiàn)一個(gè)Promise隊(duì)列小工具的文章就介紹到這了,更多相關(guān)JS Promise隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論