JavaScript使用Promise控制并發(fā)請求
開篇
在現(xiàn)代Web開發(fā)中,異步請求已經(jīng)成為了必不可少的一部分。然而,當(dāng)我們需要同時(shí)處理多個(gè)請求時(shí),如何避免請求之間的沖突和混亂呢?這就是今天我們要探討的話題——如何使用Promise控制并發(fā)請求。
在JavaScript中可以通過Promise.all()、Promise.race()、async/await等不同方式來實(shí)現(xiàn)對(duì)異步并發(fā)任務(wù)的控制。以下是一種使用Promise.all()方法實(shí)現(xiàn)并發(fā)控制的示例:
Promise.all()
const urls = ["url1", "url2", ... ,"url100"]; const maxConcurrentNum = 10; // 最大并發(fā)數(shù) // 數(shù)組分塊,chunk表示每批次數(shù)量,返回?cái)?shù)組二維數(shù)組 function chunk(arr, chunk) { let result = []; for (let i = 0, len = arr.length; i < len; i += chunk) { result.push(arr.slice(i, i + chunk)); } return result; } // 異步請求方法 function fetchUrl(url) { return new Promise((resolve, reject) => { fetch(url) .then(res => resolve(res)) .catch(err => reject(err)); }); } // 對(duì)url數(shù)組進(jìn)行分塊處理 const chunkedUrls = chunk(urls, maxConcurrentNum); (async function () { try { for (let urls of chunkedUrls) { const promises = urls.map(url => fetchUrl(url)); // 等待所有promises完成執(zhí)行,并將結(jié)果存入results數(shù)組中 const results = await Promise.all(promises); console.log('results:', results); } } catch (err) { console.error(err); } })();
以上代碼通過將數(shù)組分成多個(gè)數(shù)目相等的小數(shù)組,每次最多只開啟maxConcurrentNum個(gè)并發(fā)請求,以此來控制并發(fā)數(shù)量。每當(dāng)一組請求完成后再發(fā)送新的一批請求,可以實(shí)現(xiàn)對(duì)異步任務(wù)的并發(fā)控制。
Promise.race()
以下是使用Promise.race()方法來控制并發(fā)的示例代碼:
const promiselist = []; for (let i = 0; i < 100; i++) { const promise = fetch(`https://example.com/data${i}.json`); promiselist.push(promise); } Promise.race(promiselist) .then(response => { // handle the fastest response here }) .catch(error => { console.error(error); });
async/await
以下是使用async/await方式控制并發(fā)請求的示例代碼:
async function getData() { const promiselist = []; for (let i = 0; i < 100; i++) { const promise = fetch(`https://example.com/data${i}.json`); promiselist.push(promise); } const responses = await Promise.all(promiselist); for (const response of responses) { // handle each response here } } getData().catch(error => { console.error(error); });
在上面的代碼中,我們首先創(chuàng)建了一個(gè)async函數(shù),并在該函數(shù)中使用for循環(huán)來發(fā)送所有的請求,并將每個(gè)請求的Promise對(duì)象存儲(chǔ)在一個(gè)數(shù)組中。 然后,我們使用await關(guān)鍵字來異步等待所有Promise對(duì)象都被解決,并將解決值存儲(chǔ)在一個(gè)數(shù)組中。 最后,我們在處理每個(gè)響應(yīng)時(shí)對(duì)數(shù)組進(jìn)行迭代。
如果我們只需要等待最快的請求,我們可以使用Promise.race()方法,并將其包裝在一個(gè)async函數(shù)中。 這種方法與使用Promise.all()的方式相似,只需使用不同的Promise方法即可。
以下是使用async/await方式控制并發(fā)請求的示例代碼,其中使用Promise.race()方法:
async function getData() { const promiselist = []; for (let i = 0; i < 100; i++) { const promise = fetch(`https://example.com/data${i}.json`); promiselist.push(promise); } const response = await Promise.race(promiselist); // handle the fastest response here } getData().catch(error => { console.error(error); });
在上述代碼中,我們使用async函數(shù)來生成Promise對(duì)象,然后使用Promise.race()方法等待最快的解決Promise對(duì)象,并處理其解決值。
除了Promise.all()和Promise.race()以及async/await等方法外,還有其他用于控制并發(fā)請求的可行方法,例如:
手動(dòng)控制計(jì)數(shù)器
可以使用變量來手動(dòng)計(jì)數(shù),以控制請求并發(fā)數(shù)。例如,在循環(huán)中,當(dāng)計(jì)數(shù)器達(dá)到最大并發(fā)請求數(shù)時(shí),將其用于等待請求完成,然后遞增計(jì)數(shù)器以允許下一個(gè)請求。
以下是手動(dòng)控制計(jì)數(shù)器的示例代碼:
function getData() { const limit = 5; // maximum concurrent requests const dataUrls = ['https://example.com/data1.json', 'https://example.com/data2.json', 'https://example.com/data3.json', 'https://example.com/data4.json', 'https://example.com/data5.json', 'https://example.com/data6.json']; let counter = 0; const getDataPromise = dataUrl => { return new Promise((resolve, reject) => { fetch(dataUrl) .then(response => { counter--; resolve(response); }) .catch(error => { counter--; reject(error); }); }); }; const getDataPromises = dataUrls.map(dataUrl => { if (counter < limit) { counter++; return getDataPromise(dataUrl); } else { return new Promise(resolve => { const interval = setInterval(() => { if (counter < limit) { counter++; clearInterval(interval); resolve(getDataPromise(dataUrl)); } }, 100); }); } }); Promise.all(getDataPromises) .then(responses => { for (const response of responses) { // handle each response here } }) .catch(error => { console.error(error); }); } getData();
在上面的代碼中,我們手動(dòng)地使用計(jì)數(shù)器來控制最大并發(fā)請求數(shù),然后使用setInterval函數(shù)來等待可用的請求槽位。
使用第三方庫
此外,還有一些第三方庫可以使用,例如async.js和p-limit等。p-limit是一個(gè)專門用于控制Promise并發(fā)的小型庫??梢栽趐-limit文檔中找到更多信息和示例。
總結(jié)
通過掌握Promise的使用,我們可以輕松應(yīng)對(duì)并發(fā)請求,讓我們的Web應(yīng)用更加流暢,用戶更加滿意。所以,別讓并發(fā)請求成為你的噩夢,讓Promise來幫你解決吧!
到此這篇關(guān)于JavaScript使用Promise控制并發(fā)請求的文章就介紹到這了,更多相關(guān)Promise控制并發(fā)請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript實(shí)現(xiàn)字?jǐn)?shù)統(tǒng)計(jì)
現(xiàn)在流行的Twitter等微博客網(wǎng)站,有一個(gè)很好的用戶體驗(yàn),就是在文本框中輸入文字的時(shí)候,會(huì)自動(dòng)統(tǒng)計(jì)輸入的字符,并顯示用戶還能輸入的字符,在限制了140個(gè)字的微博客中,這樣的小提示可以很好的增強(qiáng)用戶體驗(yàn)。2015-07-07javascript+html5實(shí)現(xiàn)繪制圓環(huán)的方法
這篇文章主要介紹了javascript+html5實(shí)現(xiàn)繪制圓環(huán)的方法,實(shí)例分析了javascript實(shí)現(xiàn)html5基于canvas繪制圓環(huán)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07js實(shí)現(xiàn)新年倒計(jì)時(shí)效果
這篇文章主要介紹了js實(shí)現(xiàn)2015年新年倒計(jì)時(shí)效果,很快就要迎接新的一年,想知道距離2016還有多少天嗎?大家可以參考一下這篇文章2015-12-12JS FormData對(duì)象使用方法實(shí)例詳解
這篇文章主要介紹了JS FormData對(duì)象使用方法,結(jié)合實(shí)例形式詳細(xì)分析了FormData對(duì)象的基本功能、原理及使用方法,需要的朋友可以參考下2020-02-02JavaScript中使用typeof運(yùn)算符需要注意的幾個(gè)坑
這篇文章主要介紹了JavaScript中使用typeof運(yùn)算符需要注意的幾個(gè)坑,本文總結(jié)了4個(gè)使用typeof運(yùn)算符要注意的問題,需要的朋友可以參考下2014-11-11Cpage.js給組件綁定事件的實(shí)現(xiàn)代碼
Cpage.js是一款輕量級(jí)的Mvvm框架,使用TypeScript(JavaScript的超集)開發(fā)。下面通過本文給大家分享Cpage.js給組件綁定事件的實(shí)現(xiàn)代碼,需要的的朋友參考下吧2017-08-08JavaScript避免內(nèi)存泄露及內(nèi)存管理技巧
這篇文章主要介紹了JavaScript避免內(nèi)存泄露及內(nèi)存管理技巧,主要包括了delete應(yīng)用、閉包、DOM泄露、Timers計(jì)(定)時(shí)器泄露等等,需要的朋友可以參考下2014-09-09JS中的hasOwnProperty()和isPrototypeOf()屬性實(shí)例詳解
hasOwnProperty()和isPrototypeOf()這兩個(gè)屬性都是Object.prototype所提供:Object.prototype.hasOwnProperty()和Object.prototype.isPropertyOf(),下面給大家介紹這兩個(gè)屬性的方法和使用,一起看下吧2016-08-08