
文章目录限制并发数使用p-limit库自己封装方法合并请求减少请求数量缓存策略避免重复请求防抖 / 节流针对用户操作触发的请求懒加载 / 分页加载前端大规模并发请求指的是短时间内同时发起数十 / 上百个接口请求直接并发会导致浏览器请求阻塞同域名最多 6-8 个并发、服务器压力过载、页面卡顿、请求超时 / 失败。核心解决思路控制并发数 任务队列调度 缓存 防抖 / 节流 合并请求。限制并发数浏览器对同一个域名默认限制 6~8 个并发请求超出的请求会进入排队等待导致整体请求耗时剧增。最佳实践手动控制并发数比如 3~5 个用任务队列依次执行避免浏览器阻塞。使用p-limit库p-limit 是一个轻量级 JavaScript 库主要用于控制 Promise 或异步函数的并发执行数量防止系统因过载而崩溃安装只需运行npm install p-limit命令 。 基础用法与核心 API创建限制器引入库后调用pLimit函数并传入最大并发数返回一个限制器函数。基础用法const limit pLimit(3)表示最多同时执行 3 个任务 。高级配置支持传入对象参数如{concurrency: 5, rejectOnClear: true}决定清空队列时是否拒绝待处理任务 。执行受限任务使用限制器包装异步函数配合Promise.all等待所有任务完成。包装任务limit(() fetchData(user1))函数不会立即执行而是进入队列 。批量处理使用limit.map(iterable, mapper)可更简洁地处理数组等可迭代对象自动映射为限流任务 。状态监控与控制限制器实例暴露了多个属性用于实时监控和调整。activeCount获取当前正在执行的任务数量 。pendingCount获取排队等待的任务数量 。**clearQueue()**清空未执行的队列任务但不会取消正在运行的任务 。动态调整部分版本支持直接修改limit.concurrency动态调整并发上限 。️ 常见应用场景API 请求限流调用外部接口时限制并发数避免触发速率限制Rate Limit或导致服务器压力过大。示例设置pLimit(3)确保每秒最多发起 3 个请求配合limit.map批量获取用户数据 。批量文件处理读写大量文件时限制同时打开的文件句柄数量防止资源耗尽。示例处理上传目录文件时限制同时读取 5 个文件内容解析完成后释放资源 。任务优先级控制通过创建多个不同并发级别的限制器实现核心任务优先执行。示例高优先级任务使用pLimit(3)后台低优先级任务使用pLimit(1)确保关键业务不受阻塞 。示例代码importpLimitfromp-limitinitData();constinitData(){console.log(p-limit)constlimitpLimit(2);// 设置最大并发数量为 8constinput[// Limit函数包装各个请求limit(()fetchSomething(1)),limit(()fetchSomething(2)),limit(()fetchSomething(3)),limit(()fetchSomething(4)),limit(()fetchSomething(5)),limit(()fetchSomething(6)),limit(()fetchSomething(7)),limit(()fetchSomething(8)),];// 执行请求Promise.all(input).then(res{console.log(res)})};constfetchSomething(str){returnnewPromise((resolve,reject){setTimeout((){console.log(str)resolve(str)},1000)})}效果如图自己封装方法请求队列封装纯 JS 封装axios/fetch 通用支持限制最大并发数、任务排队、暂停、清空队列、重试严格控制并发同一时间最多 maxLimit 个请求自动排队超出并发自动进入等待队列失败重试可配置重试次数 间隔灵活管控暂停 / 恢复 / 清空无侵入不改动原有请求逻辑只包一层函数RequestQueue.jsclassRequestQueue{/** * param {number} maxLimit 最大并发数 * param {number} retryTimes 失败重试次数 * param {number} delay 重试间隔 ms */constructor(maxLimit5,retryTimes1,delay300){this.maxLimitmaxLimit;this.retryTimesretryTimes;this.delaydelay;// 等待执行队列this.waitQueue[];// 正在执行数量this.runningCount0;// 暂停状态this.isPausefalse;}// 添加请求任务addTask(task){returnnewPromise((resolve,reject){this.waitQueue.push({task,resolve,reject,retryCount:0});this.run();});}// 执行队列run(){if(this.isPause)return;// 超出并发限制 / 无等待任务 直接返回if(this.runningCountthis.maxLimit||this.waitQueue.length0)return;this.runningCount;constitemthis.waitQueue.shift();constexecute(){item.task().then(res{item.resolve(res);this.finishTask();}).catch(err{// 失败重试if(item.retryCountthis.retryTimes){item.retryCount;setTimeout(execute,this.delay);}else{item.reject(err);this.finishTask();}});};execute();}// 任务结束finishTask(){this.runningCount--;// 继续下一个this.run();}// 暂停队列pause(){this.isPausetrue;}// 恢复队列resume(){this.isPausefalse;this.run();}// 清空等待队列未执行的全部取消clearWaitQueue(){this.waitQueue[];}}exportdefaultRequestQueueindex.vuetemplatedivclassqueuedivclasstitle纯JS封装axios/fetch 通用支持限制最大并发数、任务排队、暂停、清空队列、重试/divel-button typeprimaryclickaddTask添加任务/el-buttonel-button typeinfoclickpause暂停队列/el-buttonel-button typesuccessclickresume恢复队列/el-buttonel-button typedangerclickclearWaitQueue清空等待队列/el-button/div/templatescript setupimportRequestQueuefrom/utils/RequestQueue// 模拟异步请求constfetchSomething(id){// 关键必须返回函数让队列控制什么时候执行return()newPromise((resolve){setTimeout((){console.log(执行任务,id)resolve(id)},1000)})}// 初始化队列最大并发3重试1次间隔300msconstrequestQueuenewRequestQueue(3,1,300)// 批量添加 10 个任务constaddTask(){consttaskList[1,2,3,4,5,6,7,8,9,10]taskList.forEach((id){requestQueue.addTask(fetchSomething(id)).then(res{console.log(任务完成,id,结果,res)}).catch(err{console.error(任务失败,id,err)})})}// 队列操作方法constpause()requestQueue.pause()constresume()requestQueue.resume()constclearWaitQueue()requestQueue.clearWaitQueue()/scriptstyle scoped.queue{font-size:16px;padding:20px;}.title{margin-bottom:20px;}/style效果如图合并请求减少请求数量能发 1 个请求就绝不发 10 个从源头降低并发。后端配合实现 批量接口前端把多个参数打包成数组后端一次性返回// 不推荐GET/api/user/1GET/api/user/2GET/api/user/3// 推荐批量GET/api/user?ids1,2,3缓存策略避免重复请求把相同的请求缓存起来下次再请求时直接从缓存里取。constcachenewMap();axios.interceptors.request.use(config{constkeyconfig.urlJSON.stringify(config.params);if(cache.has(key)){returnPromise.reject(已缓存${key});// 取消重复请求}cache.set(key,true);returnconfig;});防抖 / 节流针对用户操作触发的请求搜索框用防抖debounce停止输入 500ms 再发请求滚动加载用节流throttle固定时间只发一次请求懒加载 / 分页加载只加载可视区域数据不一次性请求所有数据