前端控制批量请求并发

最近准备做大文件上传的业务,就联想到前段时间很火的面试题🤦‍♂️ 假如有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))));
相关推荐
剪刀石头布啊10 分钟前
vue-react为何要虚拟dom
前端
剪刀石头布啊11 分钟前
ahooks常用的一些库,我们使用一下
前端
剪刀石头布啊13 分钟前
从git更新本地提交记录到更新已经推送到远端记录
前端
Flynt2 小时前
axios 被投毒半年后,我把 npm 的"安全防线"实测了一遍:最信任的 SHA512 是安慰剂
前端·npm·node.js
excel3 小时前
Base62 和 Base64 有什么区别?
前端
风骏时光牛马4 小时前
大模型底层架构与AI源码深度剖析
前端
掘金挖土5 小时前
前端手摸手跑路之 AI 应用开发(九)
前端·后端
中文呀7 小时前
三维 GIS 离线缓存实战:逆向 CesiumOfflineCache,并亲手为它补上"自动更新"能力
前端
前进前进前进8 小时前
TRAE 全链路实战:做了一个警示牌一键生成器:纯 Canvas、单文件、零依赖
前端