03:維護(hù)線程池
我們可以維護(hù)一個運行池和一個等待隊列垮兑,運行池中始終保持10個請求并發(fā)冷尉。
當(dāng)運行池中一個請求完成后,就從等待隊列中取出一個新請求放入運行池中運行系枪,保證運行池始終滿負(fù)荷運轉(zhuǎn),即使出現(xiàn)慢接口,也不會阻塞后續(xù)接口入池膊夹。
// 運行池,用于存儲當(dāng)前正在執(zhí)行的請求
const pool = new Set();
// 等待隊列放刨,用于存儲等待執(zhí)行的請求
const waitQueue = [];
/**
* @description: 限制并發(fā)請求的數(shù)量
* @param {*} reqFn: 請求方法(返回一個 Promise 的函數(shù))
* @param {*} max: 最大并發(fā)數(shù)
* @returns {Promise} 返回一個 Promise尸饺,當(dāng)請求完成時 resolve 或 reject
*/
const request = (reqFn, max) => {
return new Promise((resolve, reject) => {
// 檢查運行池是否已滿
const isFull = pool.size >= max;
// 包裝新的請求方法
const newReqFn = () => {
reqFn()
.then(res => {
resolve(res); // 請求成功時 resolve
})
.catch(err => {
reject(err); // 請求失敗時 reject
})
.finally(() => {
// 請求完成后,將其從運行池中移除
pool.delete(newReqFn);
// 從等待隊列中取出新的請求并放入運行池中執(zhí)行
const next = waitQueue.shift();
if (next) {
pool.add(next);
next();
}
});
};
if (isFull) {
// 如果運行池已滿浪听,將新的請求放入等待隊列
waitQueue.push(newReqFn);
} else {
// 如果運行池未滿,將新的請求加入運行池并執(zhí)行
pool.add(newReqFn);
newReqFn();
}
});
};
// 遍歷 requestList掉分,并發(fā)執(zhí)行每個請求克伊,限制最大并發(fā)數(shù)為 10
requestList.forEach(async item => {
const res = await request(item, 10); // 調(diào)用 request 函數(shù),并發(fā)執(zhí)行請求
console.log(res); // 輸出每個請求的結(jié)果
});