我司一个自研模块,AI视频生成的页面,遇见一个小场景,因为模块众多,同时请求的较多,之前因为时间紧,没考虑接口并发问题,没来及优化,今天正好有时间优化下,记录一下
我这里直接使用随机定时器来模拟并发,并发数10个,使用了Promise.all和Promise.race,以下代码方便直接观察并发情况,真实场景只需创建真实的请求数组即可
// 创建请求,使用setTimeout模拟接口返回情况
function createRequest(t) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`时间:${t}`)
}, t);
});
}
const times = [];
// 模拟生成100个随机t
for (let i = 0; i < 100; i++) {
times.push(1000+Math.ceil(i*Math.random()*30));
}
async function handleRequests(times, maxConcurrency) {
const results = [];//结果
const inRequests = [];//请求队列
for (const t of times) {
// 创建请求
const request = createRequest(t);
// push到队列里
inRequests.push(request);
// 控制并发数
if (inRequests.length >= maxConcurrency) {
// 队列里最先完成的请求出列,并获取请求值
const completedRequest = await Promise.race(inRequests);
results.push(completedRequest);
// 在队列里找出对应的请求索引,通过splice让其出列
for(let [index,req] of inRequests.entries()) {
if(completedRequest === await req) {
console.log('/t.js [30]--1',index,completedRequest,await req);
inRequests.splice(index, 1);
break
}
}
}
}
// 通过处理Promise.all,剩余的请求,并获取结果合并到results
const restResults = await Promise.all(inRequests);
results.push(...restResults);
return results;
}
handleConcurrentRequests(times, 10)
.then(async(results) => {
console.log('所有请求处理完成:', results);
})
.catch(error => {
console.error('请求处理出错:', error);
});