Chrome批量下载图片触发ERR_INSUFFICIENT_RESOURCES错误解决方案咨询
问题根因
Chrome 对同一上下文下未完成的异步请求数量有严格的资源限制,你一次性发起5000个并发请求,大量请求进入pending队列后超出浏览器内存/请求数阈值,就会抛出ERR_INSUFFICIENT_RESOURCES错误,Firefox的阈值设置更高因此可以正常执行。
可行解决方案
核心思路是限制并发请求数,浏览器同域名的默认并发请求上限为6~8,你把同一时间活跃的请求数控制在这个范围内即可,多余请求排队等待空闲 slot 再发起,既不会触发资源报错,也不会降低实际下载效率。
具体实现步骤:
- 第一步:编写轻量并发控制器,无需引入第三方依赖,逻辑如下:
// 并发请求控制器,limit为同一时间最多活跃的请求数 function concurrencyController(tasks, limit = 6) { let activeCount = 0 let index = 0 const results = [] return new Promise((resolve) => { function run() { // 所有请求执行完成后返回结果 if (index >= tasks.length && activeCount === 0) { resolve(results) return } // 有空闲slot时发起新请求 while (activeCount < limit && index < tasks.length) { const task = tasks[index] const currentIndex = index index++ activeCount++ task().then(res => { results[currentIndex] = res }).catch(err => { // 可自定义错误处理,比如记录失败的fileId后续重试 results[currentIndex] = null }).finally(() => { activeCount-- run() }) } } run() }) }
- 第二步:改造原有下载函数,改为返回Promise的形式,移除全局变量依赖:
function loadFileAndDecrypt(fileId, key, type) { return new Promise((resolve, reject) => { const req = new dh.crypto.HttpRequest(); req.setAesKey(key); const dataUrl = type == "study" ? "/v1/images/" : "/v1/dicoms/"; const url = axios.defaults.baseURL + dataUrl + fileId; req.open("GET", url, true); req.setRequestHeader("Authorization", authHeader().Authorization+"") req.setRequestHeader("Accept", "application/octet-stream, application/json, text/plain, */*"); req.responseType = "arraybuffer"; req.onload = function() { resolve(req.response); }; req.onerror = reject req.send(); }) }
- 第三步:批量发起请求时通过控制器限制并发,同时处理进度回调:
async function batchDownload(fileIdList, key, type, callback) { const total = fileIdList.length let downloadStep = 0 const step = 100 / total eventBus.$emit('updateProgressText', "downloadingFiles") // 包装所有下载任务 const tasks = fileIdList.map(fileId => () => { return loadFileAndDecrypt(fileId, key, type).then(res => { // 单请求完成后更新进度 downloadStep += step eventBus.$emit('updatePb', Math.ceil(downloadStep)) return res }) }) // 控制并发数执行 const downloadResults = await concurrencyController(tasks, 6) // 过滤失败请求,也可自定义重试逻辑 const validResults = downloadResults.filter(Boolean) callback(validResults) }
可选优化点
- 增加单请求失败重试逻辑,偶发网络错误时自动重试2~3次,避免批量下载中途失败
- 如果资源允许跨域,可替换自定义HttpRequest为原生
fetch API,内存占用更低 - 若业务允许边下载边处理,不要一次性将5000份ArrayBuffer全部存在内存中,避免后续页面卡顿
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

