专业编程基础技术教程

网站首页 > 基础教程 正文

【JS并发请求】Promise.all和Promise.race处理并发

ccvgpt 2024-07-17 18:03:55 基础教程 4 ℃

我司一个自研模块,AI视频生成的页面,遇见一个小场景,因为模块众多,同时请求的较多,之前因为时间紧,没考虑接口并发问题,没来及优化,今天正好有时间优化下,记录一下

我这里直接使用随机定时器来模拟并发,并发数10个,使用了Promise.all和Promise.race,以下代码方便直接观察并发情况,真实场景只需创建真实的请求数组即可

【JS并发请求】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);
  });

Tags:

最近发表
标签列表