前端控制批量请求并发

最近准备做大文件上传的业务,就联想到前段时间很火的面试题🤦‍♂️ 假如有100条请求,前端如何控制并发。因此在网上看了一些优化相关性能的方案,简单记录一下

不做并发

js 复制代码
async upload(Chunks) {
let queue = [...chunks];
 while (i<queue.length) {
       //此方法是自定义的上传异步方法不赘述
	let uploadRes = await this.uploadFetch(queue[i])
        if(uploadRes){
        console.log('成功')
        }else{
        // 可写异常 再重试
        //重试优化先不写  queue.push(queue[i])
        }
        i++;
     }			
  },

局限

  • 资源利用率差,对于文件片段多的时候全部接口成功等待长时间。

promnise.all分组并发

将请求数组均分为多个小数组,每次最多只开启concurrency个并发请求,以此来控制并发数量。每当一组请求完成后再发送新的一批请求,可以实现对异步任务的并发控制。

js 复制代码
        //concurrency 参数为并发数量
      **浏览器并发限制是指浏览器对同一域名同时发起的HTTP请求数量的上限**‌,通常限制在6-8个之间 **
        //Chrome/Firefox:默认6个 假如预留一个空闲位的话concurrency设置为5 
	async concurrencyUpload(chunks,concurrency) {
	let queue = [...chunks];
	while (queue.length > 0) {
	const currentChunks = queue.splice(0, concurrency);
	 await Promise.all(
	      currentChunks.map(async chunk => {
	      try {
                //此方法是自定义的上传异步方法
		await this.uploadFetch(chunk);
		} catch (err) {
		// 重试:将分片重新加入队列
                //可优化重试逻辑 控制单任务重试次数
		// queue.push(chunk);
		}
		})
		).catch(err => console.error('出错:', err));
		}
		}

局限

  • 当前批次请求全部完成后才会继续下一批次,可能存在空闲位。
  • 可能返回无序的结果。
  • 有一个请求失败了,这个 Promise.all就失败了,没有返回值。

使用队列

另一种方式是使用一个队列来手动管理并发。你可以创建一个函数来管理并发请求的发送。

js 复制代码
class RequestQueue {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent;
    this.queue = [];
    this.running = 0;
  }

  enqueue(promiseFn) {
      this.queue.push(promiseFn);
      this.processQueue();
    });
  }

  processQueue() {
    while (this.running < this.maxConcurrent && this.queue.length > 0) {
      const  promiseFn = this.queue.shift();
      this.running++;
      promiseFn()
        .then(()=>{
        //console.log('单任务返回成功')
        })
        .catch(()=>{
        // 重试:将上传任务重新加入队列
         //可优化重试逻辑 控制单任务重试次数
        this.queue.push(promiseFn)
        })
        .finally(() => {
          this.running--;
          this.processQueue(); // Process the next item in the queue
        });
    }
  }
}

// 使用示例
const queue = new RequestQueue(5); // 最大并发5个请求

// 请求函数 uploadFetch 已经是一个promise方法
chunks.forEach(chunk=>{queue.enqueue(this.uploadFetch(chunk))})

用第三方库 p-limit

安装依赖
js 复制代码
npm install p-limit
js实现
js 复制代码
import pLimit form 'p-limit';

const limit = pLimit(2); // 限制并发数为2
const results = await Promise.all(chunks.map(chunk => limit(() => this.uploadFetch(chunk))));
相关推荐
闲云一鹤1 小时前
nginx 快速入门教程 - 写给前端的你
前端·nginx·前端工程化
QCY2 小时前
「完全理解」1 分钟实现自己的 Coding Agent
前端·agent·claude
一拳不是超人2 小时前
Electron主窗口弹框被WebContentView遮挡?独立WebContentView弹框方案详解!
前端·javascript·electron
anyup2 小时前
🔥2026最推荐的跨平台方案:H5/小程序/App/鸿蒙,一套代码搞定
前端·uni-app·harmonyos
雮尘3 小时前
如何在非 Claude IDE (TARE、 Cursor、Antigravity 等)下使用 Agent Skills
前端·agent·ai编程
icebreaker3 小时前
Weapp-vite:原生模式之外,多一种 Vue SFC 选择
前端·vue.js·微信小程序
icebreaker3 小时前
重走 Vue 长征路 Weapp-vite:编译链路与 Wevu 运行时原理拆解
前端·vue.js·微信小程序
wuhen_n3 小时前
代码生成:从AST到render函数
前端·javascript·vue.js
喝咖啡的女孩3 小时前
浏览器前端指南
前端
wuhen_n3 小时前
AST转换:静态提升与补丁标志
前端·javascript·vue.js