一文分享4種Vue并發(fā)控制的實戰(zhàn)方案
在Vue項目開發(fā)中,經(jīng)常會遇到需要同時發(fā)起幾十個請求的場景(如批量數(shù)據(jù)查詢、批量提交、頁面初始化加載多接口數(shù)據(jù))。若直接同時發(fā)起所有請求,會導(dǎo)致網(wǎng)絡(luò)擁堵、接口超時、瀏覽器卡頓,甚至觸發(fā)后端接口限流,影響用戶體驗和系統(tǒng)穩(wěn)定性。本文結(jié)合Vue2/Vue3實戰(zhàn),提供4種主流并發(fā)控制方案,覆蓋不同場景,可直接落地使用,輕松管控幾十個請求的并發(fā)邏輯。
一、并發(fā)控制核心邏輯
并發(fā)控制的核心是:限制同一時間發(fā)起的請求數(shù)量,將幾十個請求分批次、有序執(zhí)行,避免一次性占用過多網(wǎng)絡(luò)資源。核心要點的2個:
- 控制并發(fā)數(shù):根據(jù)后端接口承載能力和瀏覽器限制,合理設(shè)置并發(fā)數(shù)(通常4-6個,過多易擁堵,過少效率低);
- 有序執(zhí)行:分批次發(fā)起請求,上一批請求完成(成功/失?。┖螅侔l(fā)起下一批,確保請求有序且不擁堵;
- 異常兼容:處理單個請求失敗、超時場景,避免單個請求失敗導(dǎo)致整個并發(fā)流程中斷。
以下方案均適配Vue2/Vue3,基于Axios請求庫(Vue項目主流請求工具),可直接復(fù)制到項目中修改使用。
二、4種實戰(zhàn)并發(fā)控制方案(按推薦度排序)
方案一:并發(fā)池控制(最推薦,靈活高效,適配所有場景)
核心思路:封裝一個并發(fā)池工具,將所有請求放入隊列,限制同時執(zhí)行的請求數(shù)量,當(dāng)某個請求完成后,自動從隊列中取出下一個請求執(zhí)行,循環(huán)直至所有請求完成。該方案靈活可控,可處理成功/失敗回調(diào)、超時控制,是幾十個請求并發(fā)管控的最優(yōu)選擇。
1. 封裝并發(fā)池工具(Vue2/Vue3通用)
// utils/requestPool.js
import axios from 'axios';
// 極簡版并發(fā)池(核心功能:限制并發(fā)、處理超時、返回結(jié)果)
export async function requestPool(requestList, limit = 4, timeout = 10000) {
const result = [];
let running = 0;
let queue = [...requestList];
const runRequest = async () => {
if (queue.length === 0 && running === 0) return result;
while (running < limit && queue.length > 0) {
running++;
const requestFn = queue.shift();
const index = requestList.length - queue.length - running;
try {
const res = await Promise.race([
requestFn(),
new Promise((_, reject) => setTimeout(() => reject(new Error('請求超時')), timeout))
]);
result[index] = { success: true, data: res.data };
} catch (error) {
result[index] = { success: false, error: error.message };
} finally {
running--;
await runRequest();
}
}
};
await runRequest();
return result;
}
// 極簡請求函數(shù)(按需修改url和參數(shù))
export function createRequestFn(id) {
return () => axios({ url: `/api/data/${id}`, method: 'get', timeout: 10000 });
}
2. Vue組件中使用(Vue3示例,Vue2可直接適配)
<template>
<div>
<button @click="handleBatchRequest">發(fā)起30個并發(fā)請求</button>
<div class="result">成功:{{ successCount }} 個 | 失?。簕{ failCount }} 個</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { requestPool, createRequestFn } from '@/utils/requestPool';
const successCount = ref(0);
const failCount = ref(0);
// 極簡使用示例(30個請求,并發(fā)數(shù)5)
const handleBatchRequest = async () => {
const requestList = Array.from({ length: 30 }, (_, i) => createRequestFn(i + 1));
const results = await requestPool(requestList, 5);
successCount.value = results.filter(item => item.success).length;
failCount.value = results.filter(item => !item.success).length;
};
</script>
<style scoped>
.result { margin-top: 20px; font-size: 14px; color: #333; }
</style>方案一優(yōu)勢與適配場景
- 優(yōu)勢:靈活可控,可自定義并發(fā)數(shù)、超時時間;單個請求失敗不影響整體流程;請求結(jié)果順序與發(fā)起順序一致;代碼復(fù)用性強,可全局調(diào)用。
- 適配場景:幾十個請求的批量查詢、批量提交、頁面初始化多接口加載等所有場景(最推薦)。
方案二:分批次請求(簡單易實現(xiàn),適合對順序要求高的場景)
核心思路:將幾十個請求分成若干批次,每批次發(fā)起固定數(shù)量的請求(如每批5個),等待當(dāng)前批次所有請求完成后,再發(fā)起下一批。實現(xiàn)簡單,無需復(fù)雜封裝,適合對請求順序有嚴(yán)格要求的場景(如下一批請求依賴上一批請求結(jié)果)。
1. 封裝分批次請求工具(Vue2/Vue3通用)
// utils/batchRequest.js
import axios from 'axios';
/**
* 分批次請求控制
* @param {Array} requestList - 請求列表(每個元素是請求參數(shù),如id)
* @param {Number} batchSize - 每批請求數(shù)量(默認(rèn)5個)
* @returns {Promise} - 所有請求結(jié)果數(shù)組
*/
export async function batchRequest(requestList, batchSize = 5) {
const result = [];
// 計算總批次
const totalBatch = Math.ceil(requestList.length / batchSize);
// 循環(huán)發(fā)起每批次請求
for (let i = 0; i < totalBatch; i++) {
// 截取當(dāng)前批次的請求參數(shù)
const currentBatch = requestList.slice(i * batchSize, (i + 1) * batchSize);
// 發(fā)起當(dāng)前批次的所有請求(并行)
const batchResult = await Promise.allSettled(
currentBatch.map(id =>
axios({
url: `/api/data/${id}`,
method: 'get',
timeout: 10000
}).then(res => ({ success: true, data: res.data }))
.catch(err => ({ success: false, error: err.message }))
)
);
// 將當(dāng)前批次結(jié)果存入總結(jié)果
result.push(...batchResult);
}
return result;
}
2. Vue組件中使用
<script setup>
import { ref } from 'vue';
import { batchRequest } from '@/utils/batchRequest';
const successCount = ref(0);
const failCount = ref(0);
const handleBatchRequest = async () => {
// 生成30個請求參數(shù)(如id數(shù)組)
const requestList = Array.from({ length: 30 }, (_, i) => i + 1);
// 分批次請求,每批5個
const results = await batchRequest(requestList, 5);
// 處理結(jié)果
successCount.value = results.filter(item => item.success).length;
failCount.value = results.filter(item => !item.success).length;
};
</script>方案二優(yōu)勢與適配場景
- 優(yōu)勢:實現(xiàn)簡單,無需復(fù)雜封裝;請求批次清晰,順序可控;適合下一批請求依賴上一批結(jié)果的場景。
- 適配場景:對請求順序有要求、批量提交且需分批校驗的場景(如分批提交表單數(shù)據(jù),上一批通過再提交下一批)。
方案三:Axios攔截器控制并發(fā)(全局管控,適合簡單場景)
核心思路:通過Axios的請求攔截器和響應(yīng)攔截器,維護一個“正在執(zhí)行的請求”計數(shù)器,當(dāng)計數(shù)器達到并發(fā)限制時,將后續(xù)請求存入隊列,等待正在執(zhí)行的請求完成后,再依次發(fā)起。適合簡單場景,無需在組件中單獨處理,全局統(tǒng)一管控。
1. 全局配置Axios并發(fā)控制(Vue2/Vue3通用)
// utils/axiosConfig.js
import axios from 'axios';
// 并發(fā)限制數(shù)
const CONCURRENT_LIMIT = 4;
// 正在執(zhí)行的請求計數(shù)器
let requestCount = 0;
// 請求隊列
const requestQueue = [];
// 創(chuàng)建Axios實例
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000
});
// 請求攔截器:控制并發(fā)
service.interceptors.request.use(
config => {
return new Promise(resolve => {
// 若當(dāng)前請求數(shù)未達限制,直接發(fā)起請求
if (requestCount < CONCURRENT_LIMIT) {
requestCount++;
resolve(config);
} else {
// 達到限制,存入請求隊列
requestQueue.push(resolve);
}
});
},
error => {
return Promise.reject(error);
}
);
// 響應(yīng)攔截器:請求完成后,從隊列中取出下一個請求
service.interceptors.response.use(
response => {
// 請求完成,計數(shù)器減1
requestCount--;
// 若隊列中有請求,取出并執(zhí)行
if (requestQueue.length > 0) {
const resolve = requestQueue.shift();
requestCount++;
resolve(service.defaults);
}
return response;
},
error => {
// 失敗也需計數(shù)器減1,避免隊列卡住
requestCount--;
if (requestQueue.length > 0) {
const resolve = requestQueue.shift();
requestCount++;
resolve(service.defaults);
}
return Promise.reject(error);
}
);
export default service;2. Vue組件中使用
<script setup>
import { ref } from 'vue';
import request from '@/utils/axiosConfig';
const successCount = ref(0);
const failCount = ref(0);
// 直接發(fā)起30個請求,Axios攔截器自動控制并發(fā)
const handleBatchRequest = async () => {
const requestList = [];
for (let i = 1; i <= 30; i++) {
requestList.push(
request({
url: `/api/data/${i}`,
method: 'get'
}).then(res => ({ success: true, data: res.data }))
.catch(err => ({ success: false, error: err.message }))
);
}
// 等待所有請求完成
const results = await Promise.allSettled(requestList);
successCount.value = results.filter(item => item.success).length;
failCount.value = results.filter(item => !item.success).length;
};
</script>方案三優(yōu)勢與適配場景
- 優(yōu)勢:全局統(tǒng)一管控,組件中無需單獨處理并發(fā)邏輯;侵入性低,原有請求代碼無需修改;實現(xiàn)簡單,適合快速落地。
- 適配場景:項目中所有批量請求需統(tǒng)一控制并發(fā)、無需個性化并發(fā)配置的簡單場景。
方案四:使用第三方庫(高效快捷,適合復(fù)雜場景)
核心思路:借助成熟的第三方庫(如p-limit),快速實現(xiàn)并發(fā)控制,無需自己封裝工具,適合復(fù)雜場景(如并發(fā)數(shù)動態(tài)調(diào)整、請求優(yōu)先級控制)。p-limit輕量、易用,是前端并發(fā)控制的常用庫。
1. 安裝與使用(Vue2/Vue3通用)
// 1. 安裝依賴
// npm install p-limit --save
// 2. 組件中使用
<script setup>
import { ref } from 'vue';
import axios from 'axios';
import pLimit from 'p-limit';
// 設(shè)置并發(fā)限制數(shù)為4
const limit = pLimit(4);
const successCount = ref(0);
const failCount = ref(0);
const handleBatchRequest = async () => {
// 生成30個請求函數(shù),并用p-limit包裝
const requestList = [];
for (let i = 1; i <= 30; i++) {
// 用limit包裝請求函數(shù),限制并發(fā)
requestList.push(
limit(() =>
axios({
url: `/api/data/${i}`,
method: 'get',
timeout: 10000
}).then(res => ({ success: true, data: res.data }))
.catch(err => ({ success: false, error: err.message }))
)
);
}
// 等待所有請求完成
const results = await Promise.allSettled(requestList);
successCount.value = results.filter(item => item.success).length;
failCount.value = results.filter(item => !item.success).length;
};
</script>方案四優(yōu)勢與適配場景
- 優(yōu)勢:無需自己封裝,高效快捷;支持動態(tài)調(diào)整并發(fā)數(shù)、請求優(yōu)先級;成熟穩(wěn)定,適配復(fù)雜并發(fā)場景。
- 適配場景:復(fù)雜并發(fā)需求(如動態(tài)調(diào)整并發(fā)數(shù)、設(shè)置請求優(yōu)先級)、不想自己封裝工具的場景。
三、Vue2與Vue3適配差異(關(guān)鍵注意點)
- 請求工具:兩者均使用Axios,配置方式完全一致,無差異;
- 組件寫法:Vue3使用組合式API(setup語法),Vue2使用選項式API(methods中編寫邏輯),核心并發(fā)控制邏輯完全一致;
- 環(huán)境變量:Vue3使用import.meta.env,Vue2使用process.env,修改Axios baseURL時需注意適配;
- 第三方庫:p-limit等庫適配所有Vue版本,無差異。
四、避坑指南(高頻問題)
- 并發(fā)數(shù)設(shè)置:避免設(shè)置過大(如超過10個),否則會導(dǎo)致網(wǎng)絡(luò)擁堵、后端限流;建議設(shè)置4-6個,根據(jù)后端接口承載能力調(diào)整;
- 超時控制:必須為單個請求設(shè)置超時時間,避免某個請求長時間掛起,導(dǎo)致整個并發(fā)流程卡住;
- 失敗處理:使用Promise.allSettled(而非Promise.all),避免單個請求失敗導(dǎo)致整個并發(fā)流程中斷;
- 請求順序:并發(fā)池和分批次方案可保證請求結(jié)果順序與發(fā)起順序一致,Axios攔截器方案無法保證順序(需額外處理);
- 內(nèi)存占用:幾十個請求并發(fā)時,避免存儲過多請求結(jié)果,可按需處理結(jié)果(如邊請求邊渲染),減少內(nèi)存占用。
五、總結(jié)
針對Vue中幾十個請求的并發(fā)控制,4種方案各有適配場景,可根據(jù)項目需求靈活選擇:
- 并發(fā)池控制:最推薦,靈活可控、適配所有場景,兼顧易用性和擴展性;
- 分批次請求:適合對請求順序有要求、下一批依賴上一批結(jié)果的場景;
- Axios攔截器:適合全局統(tǒng)一管控、無需個性化配置的簡單場景;
- 第三方庫:適合復(fù)雜場景、不想自己封裝工具的場景。
實際開發(fā)中,建議優(yōu)先使用“并發(fā)池控制”方案,既能靈活控制并發(fā)數(shù)、處理異常,又能保證請求順序,可直接復(fù)制本文代碼,修改請求地址和參數(shù)即可快速落地,輕松解決幾十個請求的并發(fā)難題。
以上就是一文分享4種Vue并發(fā)控制的實戰(zhàn)方案的詳細(xì)內(nèi)容,更多關(guān)于Vue并發(fā)控制的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
element table組件內(nèi)容換行的實現(xiàn)方案
這篇文章主要介紹了element table組件內(nèi)容換行的實現(xiàn)方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
Vue2子組件綁定 v-model,實現(xiàn)父子組件通信方式
這篇文章主要介紹了Vue2子組件綁定 v-model,實現(xiàn)父子組件通信方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
Vue3路由跳轉(zhuǎn)并傳遞參數(shù)的應(yīng)用場景分析
本文主要介紹在Vue3工程使用setup語法中如何進行路由跳轉(zhuǎn)并傳遞參數(shù),本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-05-05

