在開發(fā)中, 我們經(jīng)常會遇到多個請求同時進行的需求,請求不多時,我們可以直接使用
Promise.all()來進行并發(fā)請求,一般也不會有問題,但是這樣也會有弊端,比如:
- 其中一個請求比較慢,那么所有的請求就需要等待。
- 一個請求出錯,那么就代表
Promise.all()失敗,不利于后續(xù)邏輯處理。- http1.1一個域名只能同時有6個請求,當(dāng)同時并發(fā)請求比較多時,多余的請求,需要等待別的請求完成,而
Promise.all()又需要等所有請求完成,所以會更慢。- 請求數(shù)量過多,頁面上的功能又需要逐步渲染顯示,而不是等待所有接口完成。
所以,基于上面這些問題我們就需要控制請求的并發(fā),以下就是并發(fā)控制的基本代碼,同時為了方便再一個頁面中,會有多個功能模塊中需要并發(fā)控制,在RequestQueue類外面多封裝了一層。
// 并發(fā)控制
class RequestQueue {
/**
* @param {number} concurrence
*/
constructor(concurrence = 4) {
// 默認設(shè)置并發(fā)數(shù)量
this.concurrence = concurrence < 4 ? 4 : concurrence;
// 任務(wù)隊列
this.queue = [];
// 正在執(zhí)行的任務(wù)數(shù)
this.runing = 0;
// 是否暫停
this.isPause = false;
}
/**
* 加入請求任務(wù)
* @param {funtion} fn 請求任務(wù)
* @returns {void}
*/
join(fn) {
if (typeof fn !== 'function') {
console.log('請?zhí)砑右粋€函數(shù)?。?!');
return;
}
if (this.isPause || this.runing >= this.concurrence) {
this.queue.push(fn);
return;
}
this.excute(fn)
}
/**
* 執(zhí)行函數(shù)
* @param {function} fn fn
* @returns {void}
*/
async excute(fn) {
// 正在執(zhí)行的數(shù)量增加
this.runing += 1;
try {
await fn();
} catch (error) {
console.log('requestQueue執(zhí)行請求報錯~~~');
} finally {
this.runing -= 1;
this.next();
}
}
/**
* 下一個
* @returns {void}
*/
next() {
if (this.isPause || this.runing >= this.concurrence || !this.queue.length) {
return;
}
const fn = this.queue.shift();
this.excute(fn);
}
/**
* 暫停
* @returns {void}
*/
pause() {
this.isPause = true;
}
/**
* 恢復(fù)
* @returns {void}
*/
resume() {
this.isPause = false;
this.next();
}
/**
* 清理
* @returns {void}
*/
clear() {
this.isPause = false;
this.queue = [];
this.runing = 0;
}
}
const requestQueueMap = new Map();
/**
* 不同命名空間并發(fā)請求隊列
*/
class NamespaceRequestQueue {
/**
* @param {string} name 命名空間
* @param {number} concurrence 并發(fā)量
*/
constructor(name, concurrence) {
this.namespace = name;
let rq = requestQueueMap.get(name);
if (!rq) {
rq = new RequestQueue(concurrence);
requestQueueMap.set(name, rq);
}
// 當(dāng)前的請求隊列
this.requestQueue = rq;
}
join(fn) {
this.requestQueue.join(fn);
}
next() {
this.requestQueue.next();
}
pause() {
this.requestQueue.pause();
}
resume() {
this.requestQueue.resume();
}
clear() {
this.requestQueue.clear()
}
/**
* 銷毀,清空所有命名空間的并發(fā)控制
*/
destroy() {
this.requestQueue = null;
this.namespace = '';
for (const instance of requestQueueMap.values()) {
instance.clear();
}
requestQueueMap.clear();
}
}
export {
RequestQueue,
}
export default NamespaceRequestQueue;
主要有兩個類RequestQueue和NamespaceRequestQueue,其中主要功能為RequestQueue類,NamespaceRequestQueue可以通過命名空間,控制不同的并發(fā)功能模塊。