JavaScript前端控制網(wǎng)絡(luò)并發(fā)數(shù)目的常見(jiàn)方法小結(jié)
在現(xiàn)代Web應(yīng)用開(kāi)發(fā)中,提高用戶(hù)體驗(yàn)的同時(shí)要確保服務(wù)器負(fù)載平衡是至關(guān)重要的??刂魄岸税l(fā)起請(qǐng)求的并發(fā)數(shù),即限制同一時(shí)間內(nèi)進(jìn)行處理的請(qǐng)求數(shù)量,是一種有效的策略。本文將詳細(xì)介紹前端控制并發(fā)數(shù)的幾種常見(jiàn)做法,并且提供具體的代碼示例。
隊(duì)列機(jī)制
隊(duì)列是實(shí)現(xiàn)并發(fā)控制常用的數(shù)據(jù)結(jié)構(gòu)。它遵循先進(jìn)先出(FIFO)的原則,能夠按照請(qǐng)求到達(dá)的順序逐一處理。
示例:基于 Promise 的請(qǐng)求隊(duì)列
在JavaScript中,可以利用Promise
來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的請(qǐng)求隊(duì)列。下面是一個(gè)示例代碼:
class PromiseQueue { constructor(maxConcurrent) { this.maxConcurrent = maxConcurrent; this.queue = []; this.currentCount = 0; } add(promiseCreator) { return new Promise((resolve, reject) => { this.queue.push({ promiseCreator, resolve, reject }); this.tryToRun(); }); } tryToRun() { if (this.queue.length === 0 || this.currentCount >= this.maxConcurrent) { return; } this.currentCount++; const { promiseCreator, resolve, reject } = this.queue.shift(); promiseCreator().then(resolve, reject).finally(() => { this.currentCount--; this.tryToRun(); }); } }
利用此隊(duì)列可以如下方式控制并發(fā):
// 實(shí)例化隊(duì)列,設(shè)置最大并發(fā)數(shù)為 2 const queue = new PromiseQueue(2); // 添加請(qǐng)求到隊(duì)列 queue.add(() => fetch(url1)).then(handleResponse); queue.add(() => fetch(url2)).then(handleResponse); queue.add(() => fetch(url3)).then(handleResponse);
在此示例中,只有兩個(gè)請(qǐng)求會(huì)立即執(zhí)行,第三個(gè)請(qǐng)求會(huì)等待前兩個(gè)中的某個(gè)完成后再開(kāi)始。
控制并發(fā)的庫(kù)
市面上有許多專(zhuān)門(mén)用于控制并發(fā)的JavaScript庫(kù),如p-limit
, async
等。
示例:使用 p-limit 控制并發(fā)
p-limit
是一個(gè)輕量級(jí)的庫(kù),可以方便地限制并發(fā)數(shù):
import pLimit from 'p-limit'; const limit = pLimit(2); const input = [ limit(() => fetch(url1)), limit(() => fetch(url2)), limit(() => fetch(url3)), limit(() => fetch(url4)), ]; // 只有 2 個(gè)請(qǐng)求被同時(shí)處理 Promise.all(input).then(results => { // 處理結(jié)果 });
在上述代碼中,limit
函數(shù)會(huì)保證同時(shí)只有兩個(gè)請(qǐng)求在處理。
XMLHttpRequest的abort方法
在使用XMLHttpRequest(XHR)對(duì)象發(fā)送請(qǐng)求時(shí),可以在請(qǐng)求數(shù)量超過(guò)設(shè)定的并發(fā)限制時(shí)調(diào)用abort
方法來(lái)取消請(qǐng)求。
示例:使用XMLHttpRequest和abort控制并發(fā)
const MAX_CONCURRENT = 2; let concurrentCount = 0; const xhrPool = []; function fetchWithXhr(url) { if (concurrentCount >= MAX_CONCURRENT) { setTimeout(() => fetchWithXhr(url), 200); // 200ms 后重試 return; } concurrentCount++; const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.onload = () => { handleResponse(xhr.response); concurrentCount--; if (xhrPool.length > 0) { const newXhr = xhrPool.shift(); fetchWithXhr(newXhr.url); } }; xhr.onerror = xhr.onabort = () => { concurrentCount--; }; xhr.send(); } function abortExtraRequests() { while (concurrentCount > MAX_CONCURRENT) { const xhrToAbort = xhrPool.pop(); xhrToAbort.abort(); } } // 發(fā)起請(qǐng)求 fetchWithXhr("https://api.example.com/data1"); fetchWithXhr("https://api.example.com/data2"); fetchWithXhr("https://api.example.com/data3");
在此示例中,超出并發(fā)限制的請(qǐng)求將會(huì)被推遲執(zhí)行,而非立即取消;并且可以使用abortExtraRequests函數(shù)對(duì)并發(fā)數(shù)目進(jìn)行校驗(yàn),去除超過(guò)的部分。
Fetch API的AbortController
Fetch API提供了AbortController
接口,通過(guò)它可以隨時(shí)取消一個(gè)或多個(gè)請(qǐng)求。
示例:使用AbortController控制并發(fā)
const MAX_CONCURRENT = 2; let concurrentCount = 0; const controllerQueue = new Map(); async function fetchWithAbortController(url) { if (concurrentCount >= MAX_CONCURRENT) { await new Promise(resolve => setTimeout(resolve, 200)); // 200ms 后重試 return fetchWithAbortController(url); } const controller = new AbortController(); concurrentCount++; controllerQueue.set(url, controller); try { const response = await fetch(url, { signal: controller.signal }); handleResponse(await response.json()); } catch (error) { // 錯(cuò)誤處理 } finally { controllerQueue.delete(url); concurrentCount--; if (__yourCondition) { controllerQueue.get(__specificUrl).abort(); // 取消下一個(gè)請(qǐng)求 } } } // 發(fā)起請(qǐng)求 fetchWithAbortController("https://api.example.com/data1"); fetchWithAbortController("https://api.example.com/data2"); fetchWithAbortController("https://api.example.com/data3");
在這個(gè)例子中,AbortController
用于取消等待隊(duì)列中的請(qǐng)求,而且每個(gè)請(qǐng)求都有自己的AbortController
實(shí)例。
通過(guò)以上方法,可以有效控制前端并發(fā)數(shù),避免服務(wù)器過(guò)載且優(yōu)化用戶(hù)體驗(yàn)。不需修改服務(wù)器配置或縮放服務(wù)器資源即可實(shí)現(xiàn)前端請(qǐng)求的優(yōu)雅管理。這些策略對(duì)于構(gòu)建響應(yīng)速度快、資源使用高效的Web應(yīng)用至關(guān)重要。
以上就是JavaScript前端控制網(wǎng)絡(luò)并發(fā)數(shù)目的常見(jiàn)方法小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript控制網(wǎng)絡(luò)并發(fā)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
有效提高JavaScript執(zhí)行效率的幾點(diǎn)知識(shí)
這篇文章主要介紹了有效提高JavaScript執(zhí)行效率的幾點(diǎn)知識(shí),本文從JavaScript函數(shù)、JavaScript作用域、JavaScript字符串、JavaScript DOM操作、DOM重繪、DOM訪問(wèn)、DOM遍歷等方面講解了提高JavaScript執(zhí)行效率的小技巧,需要的朋友可以參考下2015-01-01JS處理數(shù)據(jù)四舍五入(tofixed與round的區(qū)別詳解)
下面小編就為大家?guī)?lái)一篇JS處理數(shù)據(jù)四舍五入(tofixed與round的區(qū)別詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10javascript實(shí)現(xiàn)保留兩位小數(shù)的多種方法
這篇文章主要介紹了javascript實(shí)現(xiàn)保留兩位小數(shù)的多種方法,如果數(shù)字的原本小數(shù)位數(shù)不到兩位,那么缺少的就自動(dòng)補(bǔ)零,感興趣的小伙伴們可以參考一下2015-12-12javascript實(shí)現(xiàn)漢字轉(zhuǎn)拼音代碼分享
這篇文章主要介紹了javascript實(shí)現(xiàn)漢字轉(zhuǎn)拼音代碼分享,非常的實(shí)用,從項(xiàng)目中分離出來(lái)的,這里分享給大家,有需要的小伙伴可以參考下。2015-04-04