html无法限制并发上传,需用promise队列+并发计数器控流;fetch可用abortcontroller中断,xmlhttprequest需手动标记取消;大文件上传后须及时释放formdata引用并清理url对象,推荐并发数3–5。

HTML 本身不提供限制并发上传数量的能力,multiple 只控制能否多选,XMLHttpRequest 或 fetch 每次调用都独立发起请求。真正能控并发的,是你自己写的调度逻辑——核心就两条:队列 + 计数器。
用 Promise 队列 + 并发计数器手动控流
别直接 files.forEach(uploadFile),那会瞬间发出全部请求。得把每个上传包装成 Promise,再用一个运行中计数器(比如 activeCount = 0)和最大阈值(如 MAX_CONCURRENT = 3)来节流。
- 每次准备发新请求前,先判断
activeCount ;不满足就暂存进任务队列 - 在
xhr.onloadend或fetch().then().catch()结束后,activeCount--,再从队列取下一个执行 - 注意必须用
onloadend(不是onload),因为上传失败时onload不触发,但onloadend总会触发 - 示例片段:
let activeCount = 0; const queue = []; function uploadNext() { if (activeCount >= 3 || queue.length === 0) return; activeCount++; const task = queue.shift(); task().finally(() => { activeCount--; uploadNext(); }); }
AbortController 对 fetch 有效,对 XMLHttpRequest 无效
用户点击“取消上传”时,已发出的 fetch 请求可直接用 AbortController 中断;但 XMLHttpRequest 不支持 signal,强行调 xhr.abort() 只对已发出的请求生效,队列里还没创建实例的请求根本无从 abort。
- 对
fetch:构造时传{ signal: controller.signal },后续调controller.abort()即可 - 对
XMLHttpRequest:需在任务对象里加isCancelled = false标志,发起前检查,回调开头也检查,否则可能执行已完成却已失效的逻辑 - 中断大文件上传时,服务端仍可能收到部分数据,后端必须做幂等处理(比如按文件 hash 去重)
FormData 引用不释放会导致内存泄漏
高频并发上传时,反复用 new FormData().append('file', file),若 file 是大体积 Blob 或 File 实例,又没及时切断引用,Chrome 内存占用会飙升,甚至卡死。
- 上传成功后立刻设
file = null,尤其避免在类属性或闭包中长期持有File实例 - 不要把整个
FileList存进 React state 或全局变量;改用数组存储精简信息(如{ name, size, url: URL.createObjectURL(file) }),上传完立即URL.revokeObjectURL(url) - 用 Chrome DevTools 的 Memory 面板观察 JS Heap,筛选 “Detached” 节点,能快速定位残留的
File引用
并发数硬限建议设在 3–5 之间,再高浏览器连接池和服务器压力都会明显上升;更关键的是,很多人忘了队列里未发出的任务也要响应取消信号——这部分最容易漏处理,结果用户点了暂停,后台还在默默发请求。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











