如何正确发起数千次$.getJSON请求避免出现ERR_INSUFFICIENT_RESOURCE错误
多JSON文件请求性能优化方案
你遇到的ERR_INSUFFICIENT_RESOURCE报错本质是一次性发起4万次异步请求导致的内存溢出:Chrome同域名下最多同时并发6~8个请求,剩余请求全部堆积在内存队列中,叠加请求回调、返回数据的内存占用,直接触发资源不足异常,同时阻塞主线程导致页面卡顿。
下面是可落地的优化方案,按优先级从高到低排列:
1. 最高优先级:添加请求并发控制
限制同时发起的请求数量(建议设置为5~8,和浏览器同域名并发上限对齐),每完成一个请求再推入下一个任务,从根源避免内存队列溢出。
可直接使用如下轻量并发控制器实现:
/** * 并发请求控制 * @param {Array<Function>} tasks 任务列表,每个元素是返回Promise的请求函数 * @param {Number} limit 最大并发数 * @returns {Promise<Array>} 所有请求的返回结果 */ async function limitRequest(tasks, limit = 6) { const result = []; const executing = []; for (const task of tasks) { // 包装任务,保证执行顺序 const p = Promise.resolve().then(() => task()); result.push(p); // 并发数达到上限时,等待任意一个请求完成再推入下一个 if (tasks.length >= limit) { const e = p.then(() => executing.splice(executing.indexOf(e), 1)); executing.push(e); if (executing.length >= limit) { await Promise.race(executing); } } } return Promise.all(result); } // 业务侧使用示例 // 1. 生成第一批2万请求的任务队列 const batch1Tasks = Array.from({length: 20000}, (_, index) => { return () => $.getJSON(`example.org/${index + 1}.json`); }); // 2. 按并发数6执行第一批请求,拿到返回结果 const arrayone = await limitRequest(batch1Tasks, 6); // 3. 生成第二批请求任务队列 const batch2Tasks = Array.from({length: 20000}, (_, index) => { return () => $.getJSON(`example.org/someplace/${index + 1}.json`); }); // 4. 执行第二批请求 const arraytwo = await limitRequest(batch2Tasks, 6); // 5. 执行对比逻辑 // ... 你原有对比代码
仅添加并发控制即可解决卡顿和报错问题,性能可提升5~10倍。
2. 架构级优化:批量合并请求
如果可以调整服务端接口逻辑,优先将单文件查询接口改为批量查询接口:单次请求传入最多100个文件ID,服务端一次性返回对应100个JSON内容,可将4万次请求直接压缩到400次,性能提升超过100倍,是最优解决方案。
3. 内存优化:边请求边对比
不需要全量存储arrayone和arraytwo两个2万条的大数组,可以调整逻辑为:每拿到1个序号对应的两组JSON数据,就立即完成对比,不需要留存全量数据,内存占用可降低90%以上。
4. 细节优化:替换请求API
可使用原生fetch API替代$.getJSON,减少jQuery封装带来的额外性能开销,同时支持AbortController随时终止冗余请求。
内容的提问来源于stack exchange,提问作者pumib
相关产品推荐
相关产品推荐

