JavaScript模擬隊(duì)列的用法詳解
場(chǎng)景
場(chǎng)景一:
有幾百條數(shù)據(jù)需要傳遞給后端,但是后端每次最多只能接收10條數(shù)據(jù)
場(chǎng)景二:
在彈出第一個(gè)彈框并關(guān)閉后再彈第二個(gè)彈窗(或者廣告一類的)
我想這些需求大家應(yīng)該都了解過,或者遇到過,我們可能第一反應(yīng)是通過定時(shí)器或者Promise來處理,現(xiàn)在我告訴你完全可以通過隊(duì)列的方式來處理。我會(huì)寫一些示例,如果運(yùn)用到工作中請(qǐng)根據(jù)自己的需求進(jìn)行修改即可。
說明
JavaScript 隊(duì)列(Queue)是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),它用于存儲(chǔ)按順序排列的元素,并支持插入新元素和刪除元素的操作。隊(duì)列在計(jì)算機(jī)科學(xué)中有著廣泛的應(yīng)用,例如在操作系統(tǒng)中實(shí)現(xiàn)任務(wù)調(diào)度、在數(shù)據(jù)壓縮中使用哈夫曼編碼等。在JavaScript中,隊(duì)列也常用于實(shí)現(xiàn)異步編程和控制流程。 JavaScript隊(duì)列通??梢酝ㄟ^內(nèi)置的Array對(duì)象實(shí)現(xiàn),或者使用第三方庫如queue-lib。Array對(duì)象提供了push()和shift()方法,可以模擬隊(duì)列的入隊(duì)和出隊(duì)操作。
簡(jiǎn)單隊(duì)列
我們從下面的模擬隊(duì)列中可以看出,我們?cè)趫?zhí)行的時(shí)候makeRequest(模擬請(qǐng)求)是依次開始執(zhí)行,那么我們想同時(shí)執(zhí)行多個(gè)請(qǐng)求呢?我們想間隔一段時(shí)間在發(fā)送請(qǐng)求呢?那我們接到看下面這個(gè)示例。
class RequestQueue { constructor() { this.queue = []; // 請(qǐng)求隊(duì)列 this.running = 0; // 當(dāng)前正在運(yùn)行的請(qǐng)求數(shù)量 } // 將請(qǐng)求添加到隊(duì)列中 enqueue(request) { this.queue.push(request); this.run(); // 檢查是否可以運(yùn)行新的請(qǐng)求 } // 檢查并運(yùn)行請(qǐng)求 run() { if (this.running !== 0 || !this.queue.length) return; const request = this.queue.shift(); this.execute(request); this.running++; } // 執(zhí)行請(qǐng)求 execute(request) { request().finally(() => { this.running--; if (this.queue.length <= 0) return; this.run(); }); } } // 模擬一個(gè)異步請(qǐng)求 function makeRequest(id) { return new Promise((resolve) => { console.log(`正在發(fā)送請(qǐng)求 ${id}`); setTimeout(() => { console.log(`請(qǐng)求 ${id} 完成`); resolve(id); }, 1000); }) } // 創(chuàng)建請(qǐng)求隊(duì)列并添加10個(gè)請(qǐng)求 const queue = new RequestQueue(1, 100); for (let i = 1; i <= 10; i++) { queue.enqueue(async () => await makeRequest(i)); };
完整隊(duì)列
我們從該隊(duì)列中可以看出,我們可以去控制自己的并發(fā)量以及間隔時(shí)間了,那么我們?cè)诳紤]下。如果隊(duì)列執(zhí)行完成了,我們?cè)趺粗滥??等等。那我們就給他補(bǔ)充完全吧?。ㄟ@只是我想到的,我沒考慮到的你們也可以自己完善哈)
class RequestQueue { constructor(limit,delay) { this.limit = limit; // 最大并發(fā)請(qǐng)求數(shù) this.delay = delay; // 批次間隔時(shí)間(毫秒) this.queue = []; // 請(qǐng)求隊(duì)列 this.running = 0; // 當(dāng)前正在運(yùn)行的請(qǐng)求數(shù)量 } // 將請(qǐng)求添加到隊(duì)列中 enqueue(request) { this.queue.push(request); this.run(); // 檢查是否可以運(yùn)行新的請(qǐng)求 } // 檢查并運(yùn)行請(qǐng)求 run() { while (this.running < this.limit && this.queue.length > 0) { const request = this.queue.shift(); this.execute(request); this.running++; } } // 執(zhí)行請(qǐng)求 execute(request) { request().finally(() => { this.running--; if (this.queue.length > 0) { setTimeout(() => { this.run(); }, this.delay); } }); } } // 模擬一個(gè)異步請(qǐng)求 function makeRequest(id) { return new Promise((resolve) => { console.log(`發(fā)起請(qǐng)求 ${id}`); setTimeout(() => { console.log(`請(qǐng)求 ${id} 完成`); resolve(id); }, 100); }) } // 創(chuàng)建請(qǐng)求隊(duì)列并添加10,000個(gè)請(qǐng)求 const queue = new RequestQueue(5,1000); for (let i = 1; i <= 20; i++) { queue.enqueue(async () => await makeRequest(i)); };
補(bǔ)充完整隊(duì)列
我們?cè)诒O(jiān)聽隊(duì)列是否完成的時(shí)候注意一個(gè)事,就是Promise在返回的時(shí)候一定要在成功的時(shí)候才返回。至于原因,你們可以自己去嘗試哈。
class RequestQueue { timer = null; // 定時(shí)器 constructor(limit, delay) { this.limit = limit; // 最大并發(fā)請(qǐng)求數(shù) this.delay = delay; // 批次間隔時(shí)間(毫秒) this.queue = []; // 請(qǐng)求隊(duì)列 this.running = 0; // 當(dāng)前正在運(yùn)行的請(qǐng)求數(shù)量 } // 將請(qǐng)求添加到隊(duì)列中 enqueue(request) { this.queue.push(request); this.run(); // 檢查是否可以運(yùn)行新的請(qǐng)求 } // 檢查并運(yùn)行請(qǐng)求 run() { while (this.running < this.limit && this.queue.length > 0) { const request = this.queue.shift(); this.execute(request); this.running++; } } // 執(zhí)行請(qǐng)求 execute(request) { request().finally(() => { this.running--; if (this.queue.length > 0) { setTimeout(() => { this.run(); }, this.delay); } }); } // 監(jiān)聽隊(duì)列是否完成 isQueueEmpty() { return new Promise((resolve, reject) => { this.timer = setInterval(() => { if (this.queue.length === 0 && this.running === 0) { clearInterval(this.timer); this.timer = null; resolve(true); } }, 1000); }) } } // 模擬一個(gè)異步請(qǐng)求 function makeRequest(id) { return new Promise((resolve) => { console.log(`發(fā)起請(qǐng)求 ${id}`); setTimeout(() => { console.log(`請(qǐng)求 ${id} 完成`); resolve(id); }, 100); }) } // 創(chuàng)建請(qǐng)求隊(duì)列并添加10,000個(gè)請(qǐng)求 const queue = new RequestQueue(5, 1000); for (let i = 1; i <= 20; i++) { queue.enqueue(async () => await makeRequest(i)); }; // 執(zhí)行完成返回ture queue.isQueueEmpty().then(res=>{ console.log(res); })
總結(jié)
以上就是JavaScript模擬隊(duì)列的基礎(chǔ)寫法用法,大家也可以根據(jù)你們的需要進(jìn)行修改和完善。
到此這篇關(guān)于JavaScript模擬隊(duì)列的用法詳解的文章就介紹到這了,更多相關(guān)JavaScript模擬隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解JavaScript如何實(shí)現(xiàn)并發(fā)控制的Promise隊(duì)列調(diào)度器
- JavaScript數(shù)據(jù)結(jié)構(gòu)yocto queue隊(duì)列鏈表代碼分析
- JS數(shù)據(jù)結(jié)構(gòu)與算法中的隊(duì)列結(jié)構(gòu)詳解
- JS數(shù)據(jù)結(jié)構(gòu)之隊(duì)列結(jié)構(gòu)詳解
- JavaScript實(shí)現(xiàn)一個(gè)Promise隊(duì)列小工具
- JS 中實(shí)現(xiàn)一個(gè)串型異步函數(shù)隊(duì)列
相關(guān)文章
javascript實(shí)現(xiàn)表單驗(yàn)證
這篇文章主要介紹了javascript實(shí)現(xiàn)表單驗(yàn)證的相關(guān)資料,以一個(gè)完整的實(shí)例對(duì)javascript實(shí)現(xiàn)表單驗(yàn)證的方法進(jìn)行分析,感興趣的小伙伴們可以參考一下2016-01-01二級(jí)域名或跨域共享Cookies的實(shí)現(xiàn)方法
適用于Asp。 在主域名設(shè)置的Cookie,在各子域名共用;適用于博客等提供二級(jí)域名。這個(gè)問題,以網(wǎng)上有眾多帖子,可惜都沒有完整解決。2008-08-08完美實(shí)現(xiàn)八種js焦點(diǎn)輪播圖(上篇)
這篇文章主要介紹了完美實(shí)現(xiàn)八種js焦點(diǎn)輪播圖的具體資料,基于完美運(yùn)動(dòng)框架move2.js而完成的八種焦點(diǎn)錄播圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07利用js正則表達(dá)式驗(yàn)證手機(jī)號(hào),email地址,郵政編碼
利用js正則表達(dá)式驗(yàn)證手機(jī)號(hào),email地址,郵政編碼。需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-01-01JavaScript 身份證號(hào)有效驗(yàn)證詳解及實(shí)例代碼
這篇文章主要介紹了JavaScript 身份證號(hào)有效驗(yàn)證詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10