前端控制批量请求并发

最近准备做大文件上传的业务,就联想到前段时间很火的面试题🤦‍♂️ 假如有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))));
相关推荐
bearpping2 小时前
Nginx 配置:alias 和 root 的区别
前端·javascript·nginx
@大迁世界2 小时前
07.React 中的 createRoot 方法是什么?它具体如何运作?
前端·javascript·react.js·前端框架·ecmascript
January12072 小时前
VBen Admin Select 选择框选中后仍然显示校验错误提示的解决方案
前端·vben
. . . . .3 小时前
前端测试框架:Vitest
前端
xiaotao1313 小时前
什么是 Tailwind CSS
前端·css·css3
战南诚4 小时前
VUE中,keep-alive组件与钩子函数的生命周期
前端·vue.js
发现一只大呆瓜4 小时前
React-彻底搞懂 Redux:从单向数据流到 useReducer 的终极抉择
前端·react.js·面试
霍理迪4 小时前
Vue的响应式和生命周期
前端·javascript·vue.js
李剑一4 小时前
别再瞎写了!Cesium 模型 360° 环绕,4 套源码全公开,项目直接用
前端