前端面试题:如何控制批量接口请求的最大并发数

发布时间:2026/8/28 7:18:54

前端面试题:如何控制批量接口请求的最大并发数
前端面试题如何控制批量接口请求的最大并发数 题目一次性需要发送 100 条接口请求不能全部并发会压垮后端也不能完全串行太慢如何控制最大并发数请手写一个并发控制器。 核心思路一句话用任务队列 运行计数器 完成即补位的并发池模型将并发数锁定在阈值内兼顾吞吐量与服务端稳定性。 主要矛盾 vs 次要矛盾层级矛盾说明主要矛盾前端吞吐量 vs 后端承载上限并发过高→网关限流/502并发过低→用户等待过长次要矛盾①结果顺序 vs 完成顺序并发执行完成顺序不确定业务可能需要按原始顺序聚合次要矛盾②失败处理 vs 整体流程单条失败不应阻塞其余任务但需可追溯次要矛盾③可中断性 vs 已发出请求用户取消时已 in-flight 的请求无法真正撤回只能丢弃响应 三种方案对比┌─────────────────────────────────────────────────────────────────┐ │ 方案APromise.all 全并发 │ │ 100个请求同时发出 → 瞬间打满网关 → 触发限流/超时 → ❌ 不可用 │ ├─────────────────────────────────────────────────────────────────┤ │ 方案Bfor await 串行 │ │ 一个完成再发下一个 → 100×RTT → 速度极慢 → ❌ 浪费网络空闲 │ ├─────────────────────────────────────────────────────────────────┤ │ 方案C并发控制池限流池 ✅ 最优解 │ │ 固定 N 个并发槽位完成一个补一个 → 效率 稳定性兼得 │ └─────────────────────────────────────────────────────────────────┘维度Promise.all串行 await并发池并发数100不可控1N可配置总耗时≈1×RTT理想≈100×RTT≈⌈100/N⌉×RTT服务端压力极高易崩极低可控适用场景≤5个无依赖请求强顺序依赖批量操作推荐️ 并发池架构图文本版┌──────────────────────────────┐ │ 任务队列 (Queue) │ │ [task5, task6, ... task100] │ └──────────┬───────────────────┘ │ shift() 取队首 ▼ ┌─────────────────────────────────────────────────────┐ │ 并发调度器 (Scheduler) │ │ │ │ runningCount: 当前运行数 maxConcurrency: N │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ Slot 1 │ │ Slot 2 │ │ Slot N │ ← N个槽位 │ │ │ task1 ▶ │ │ task2 ▶ │ │ task3 ▶ │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │done │done │done │ │ ▼ ▼ ▼ │ │ runningCount-- → 从队列取新任务 → runningCount │ └─────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────┐ │ 结果收集 (按原始index存放) │ │ results[0..99] │ └──────────────────────────────┘ 终止条件queue.length 0 runningCount 0 核心流程文本流程图开始 │ ├─ 1. 将 100 个请求封装为 () Promise 函数推入 taskQueue │ ├─ 2. 初始化循环 min(maxConcurrency, queue.length) 次 │ 调用 runNext() 启动首批任务 │ ├─ 3. runNext() 内部 │ ├─ runningCount │ ├─ 执行 task() │ ├─ .then → 收集结果到 results[index] │ ├─ .catch → 记录错误 / 触发重试 │ └─ .finally → │ ├─ runningCount-- │ ├─ 队列非空→ runNext()补位 │ └─ 队列空 runningCount0→ resolve 整体 Promise │ └─ 4. 返回 Promiseresults[]调用方 await 获取全部结果 完整示例代码生产级classConcurrencyScheduler{constructor({maxConcurrency5,retries0,retryDelay1000}{}){this.maxmaxConcurrency;this.retriesretries;this.retryDelayretryDelay;this.queue[];// 等待队列this.running0;// 当前运行数this.results[];// 按原始顺序收集结果this.errors[];// 错误收集this.isPausedfalse;// 中断标志this._resolvenull;}/** 添加任务task 是返回 Promise 的函数index 用于结果排序 */addTask(task,index){this.queue.push({task,index});}/** 启动调度 */start(){returnnewPromise((resolve){this._resolveresolve;constinitialCountMath.min(this.max,this.queue.length);for(leti0;iinitialCount;i){this._runNext();}// 边界队列为空0个任务if(this.queue.length0this.running0){resolve(this.results);}});}/** 中断清空队列不再补位已发出的请求无法撤回但结果会被丢弃 */abort(){this.isPausedtrue;this.queue[];}async_runNext(){if(this.isPaused||this.queue.length0){this._checkDone();return;}const{task,index}this.queue.shift();this.running;try{constresultawaitthis._execWithRetry(task);this.results[index]{status:fulfilled,value:result};}catch(err){this.results[index]{status:rejected,reason:err};this.errors.push({index,error:err});}finally{this.running--;this._runNext();// 补位}}/** 带重试的执行 */async_execWithRetry(task,attempt0){try{returnawaittask();}catch(err){if(attemptthis.retries){awaitthis._sleep(this.retryDelay*(attempt1));// 递增延迟returnthis._execWithRetry(task,attempt1);}throwerr;}}_checkDone(){if(this.queue.length0this.running0this._resolve){this._resolve(this.results);}}_sleep(ms){returnnewPromise((r)setTimeout(r,ms));}}使用示例// 模拟 100 个接口请求consturlsArray.from({length:100},(_,i)/api/data/${i});constschedulernewConcurrencyScheduler({maxConcurrency:6,// 最大 6 个并发retries:2,// 失败最多重试 2 次retryDelay:1000,});urls.forEach((url,index){scheduler.addTask(()fetch(url).then(resres.json()),index// 保证结果按原始顺序);});constresultsawaitscheduler.start();console.log(results);// [{status:fulfilled, value:...}, ...] 长度100顺序一致中断示例// 用户点击取消按钮cancelBtn.onclick()scheduler.abort(); 使用场景场景说明推荐并发数批量导入Excel→逐条调接口几千条数据逐条提交5~10批量查询详情列表页补充信息100个ID查详情6~8批量文件上传分片大文件切片并发上传3~6受带宽限制图片批量压缩/预览前端本地处理 上传4~6爬虫/数据采集合规前提下控制对目标站点压力2~4⚠️ 边界场景 注意事项边界处理方式任务数为 0start() 直接 resolve([])任务数 maxConcurrency全部立即执行无需排队单个任务永远 pending加超时包装Promise.race([task(), timeout(ms)])全部失败收集 errors不阻塞整体流程最终统一上报内存溢出10万任务分批 push 入队 / 配合 Web Worker / 后端分片接口浏览器同域并发限制HTTP/1.1 同域最多 6 连接HTTP/2 多路复用无此限制AbortController 真正取消配合 fetch 的 signal 参数abort 时真正断开连接超时包装补充functionwithTimeout(promiseFn,ms10000){return()Promise.race([promiseFn(),newPromise((_,reject)setTimeout(()reject(newError(TIMEOUT)),ms)),]);}scheduler.addTask(withTimeout(()fetch(url),8000),index); 与相关 API 的关系补充知识点API作用局限Promise.all全并发全部成功才 resolve无法限流一个失败全挂Promise.allSettled全并发收集所有结果同样无法限流Promise.any全并发一个成功即 resolve场景不同p-limitnpm现成并发控制库原理同本文生产可直接用p-queuenpm支持优先级、暂停、事件更重适合复杂调度面试手写考察的是原理理解生产中可用p-limit一行搞定importpLimitfromp-limit;constlimitpLimit(6);constresultsawaitPromise.all(urls.map((url,i)limit(()fetch(url)))); 面试满分答案话术版面对大批量接口请求我采用并发池限流方案设定最大并发阈值如 6将所有请求封装为返回 Promise 的函数存入任务队列初始启动 N 个任务占满并发槽位任一任务完成后计数器减一立即从队列头部取出新任务补位计数器加一队列为空且运行数为零时整体完成按原始顺序返回结果数组。这样做既避免瞬时并发打崩网关又比串行高效数倍。在此基础上我还做了三层扩展失败重试单任务失败自动重试 N 次递增延迟重试耗尽才标记失败中断取消暴露 abort 方法清空队列、停止补位配合 AbortController 真正取消 in-flight 请求超时兜底用 Promise.race 包装防止单任务 hang 住占满槽位。如果数据量特别大上万条还会结合后端分页/分片接口从源头减少请求数前端再配合并发池双管齐下。以上即本题完整核心干货掌握队列 计数器 补位三要素即可应对所有变体。

相关新闻

Loop Engineering与原生模型切换:构建Codex与Claude多模型工作流

Loop Engineering与原生模型切换:构建Codex与Claude多模型工作流

2026/8/28 7:08:53

做 AI 编程落地时,很多人都会遇到一个尴尬的局面:同一个模型并不能包打天下。写脚本、改配置时,Codex 可能一轮就完成任务;做架构评审、改测试时,Claude 的理解往往更细腻;而当你希望批处理多个仓库任务时&…

C++ STL核心:begin()与end()函数原理、应用与迭代器失效解析

C++ STL核心:begin()与end()函数原理、应用与迭代器失效解析

2026/8/28 7:08:53

1. 项目概述:为什么begin()和end()是STL的“任督二脉”如果你刚开始接触C标准模板库(STL),可能会觉得容器、迭代器、算法这些概念纷繁复杂,有点无从下手。但我想告诉你,无论你用的是vector、list、map还是s…

Matlab线性规划建模实战:从linprog函数到生产计划优化

Matlab线性规划建模实战:从linprog函数到生产计划优化

2026/8/28 7:08:53

1. 项目概述:当数学建模遇上线性规划如果你正在准备数学建模竞赛,或者在工作中需要处理资源分配、生产计划、成本优化这类问题,那你大概率绕不开“线性规划”这四个字。简单来说,线性规划就是在一系列线性等式或不等式的约束条件下…

蓝桥杯单片机国赛实战:从硬件驱动到软件架构的嵌入式系统设计

蓝桥杯单片机国赛实战:从硬件驱动到软件架构的嵌入式系统设计

2026/8/28 8:28:57

1. 项目概述:从“蓝桥杯国赛”到实战能力跃迁提起“蓝桥杯”,尤其是在单片机赛道,很多电子、自动化、计算机相关专业的朋友都不会陌生。它不仅仅是一个竞赛,更像是一个检验你从书本知识到实际工程能力转化的“试金石”。我参加过第…

毕设开源 stm32智能鱼缸监控投喂系统(源码+硬件+论文)

毕设开源 stm32智能鱼缸监控投喂系统(源码+硬件+论文)

2026/8/28 8:28:57

👆👆 完整项目获取方式👆👆完整项目获取方式👆👆完整项目获取方式👆👆完整项目获取方式👆👆 文章目录 👆👆 完整项目获取方式&#x1…

你把房子变成了家手机版游戏中文汉化版免费下载安装教程附带攻略你把房子变成了家手机汉化版下载安装教程游戏攻略安卓版app鸿蒙版苹果版IOS电脑版安装包下载地址

你把房子变成了家手机版游戏中文汉化版免费下载安装教程附带攻略你把房子变成了家手机汉化版下载安装教程游戏攻略安卓版app鸿蒙版苹果版IOS电脑版安装包下载地址

2026/8/28 8:28:57

📢提示:资源链接地址放在文章结尾👇👇,往下翻就行 📢提示:资源链接地址放在文章结尾👇👇,往下翻就行 你把房子变成了家手机版游戏中文汉化版免费下载安装教…

MATLAB函数句柄@符号详解:从匿名函数到数学建模实战

MATLAB函数句柄@符号详解:从匿名函数到数学建模实战

2026/8/28 8:28:57

1. 从“”符号说起:函数句柄,MATLAB数学建模的“瑞士军刀”在MATLAB的数学建模世界里,你迟早会遇到一个看起来有点“神秘”的符号:。它不像加减乘除那样直观,也不像for、if那样有明确的流程控制含义。但当你开始接触优…

VMware虚拟机安装CentOS7全攻略

VMware虚拟机安装CentOS7全攻略

2026/8/28 8:28:57

一、介绍centOS是由基于centOS社区RHEL源代码开发的开源操作系统,非常适合我们liux的基础训练,一个liux系统会了那么其他的系统也都迎刃而解了。那么让我们一起来学习如何在VMware虚拟机里面安装一个centOS系统吧。二、准备工作以及镜像1、我准备了一个V…

车规级降压DC-DC转换器设计实战:从选型到EMC调试全解析

车规级降压DC-DC转换器设计实战:从选型到EMC调试全解析

2026/8/28 8:18:56

这几年的汽车电子项目,我几乎每周都要跟车规级降压DC-DC转换器(Automotive-Grade Step-Down DC-DC Converters)打交道。很多硬件工程师一开始容易把这件事看简单了:不就是个Buck降压芯片嘛,把12V降到5V或者3.3V&#x…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/27 11:10:02

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/27 7:25:23

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/28 7:34:42

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

基于Claude Code的开源AI求职框架:从职位搜索到Offer的全自动化闭环

基于Claude Code的开源AI求职框架:从职位搜索到Offer的全自动化闭环

2026/8/28 0:08:32

当AI助手能够独立完成从职位匹配、简历定制到面试准备的全链路求职流程时,求职不再是一场信息战,而是一场工程化战役。框架概述:本地运行的AI求职引擎这是一个构建在Claude Code之上的开源AI求职框架,核心理念是"在工作者的机…

Godot 4 仿 agar.io:相机缩放被 max_zoom 卡死,窗口越大球越小的根因与修复

Godot 4 仿 agar.io:相机缩放被 max_zoom 卡死,窗口越大球越小的根因与修复

2026/8/28 0:08:32

1. 问题现象 在 Godot 4 仿 agar.io 的 2D 项目中,相机缩放设计为「由球组整体尺寸决定」,世界可见高度恒定,窗口只作为视口裁剪。默认小窗口 1280x720 时相机高度正常;但窗口最大化到 2940x1912 后,视角被明显拉远、…

从软件测试大赛到实战:Java+Selenium自动化测试进阶指南

从软件测试大赛到实战:Java+Selenium自动化测试进阶指南

2026/8/28 0:08:32

1. 缘起:从校园到赛场,我的软件测试之路几年前,我还是一个在校园里对着Java课本和“Hello World”程序挠头的普通学生。软件测试对我来说,只是一个在开发流程末尾、用鼠标点点按钮的模糊概念。直到我偶然在学校的公告栏上看到了“…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/28 7:35:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/28 7:34:51

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/28 7:34:35

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…