Chrome中使用$.when并行发起100个AJAX请求失败求助
关于Chrome中批量AJAX请求部分失败的原因及解决方案
你遇到的问题确实和浏览器并发连接限制以及可能的超时设置密切相关,下面详细拆解原因和可行的解决办法:
一、核心原因:浏览器的并发连接限制
Chrome(以及绝大多数现代浏览器)对同一域名的并发HTTP请求数有默认限制:
- 对于HTTP/1.1协议,默认是6个并发连接
- 对于HTTP/2协议,虽然支持多路复用(理论上无硬性并发数限制),但很多服务器可能未开启该协议,或者仍会有实际的资源承载上限
当你一次性发起100个请求时,浏览器会把超出并发数的请求放入等待队列,只有当前面的请求完成后,才会依次执行队列中的请求。如果队列等待时间过长,就容易触发请求超时,导致部分请求直接失败。
二、其他可能的诱因
- AJAX超时设置不合理:如果你的
ajaxUploadTrackable方法没有设置足够长的超时时间,排队的请求可能还没等到执行就被判定为超时失败。 - 服务器端限流:很多服务器会设置请求频率限制(比如每分钟最多接受N个请求),一次性发起100个请求可能触发服务器的限流机制,直接拒绝部分请求。
- $.when的局限性:jQuery的
$.when在任何一个请求失败时,会立即触发fail回调,不会等待其他请求完成。如果没处理fail回调,可能误以为是请求本身失败,但实际上是$.when的逻辑导致后续处理未执行。
三、针对性解决方案
1. 控制并发请求数量
实现一个批量并发控制函数,每次只发起指定数量的请求(比如匹配浏览器默认的6个),完成一批后再发起下一批,避免请求排队超时。示例代码:
function batchRequest(items, batchSize) { let allResults = []; let currentIndex = 0; function processNextBatch() { if (currentIndex >= items.length) { return Promise.resolve(allResults); } // 截取当前批次的请求项 const batchItems = items.slice(currentIndex, currentIndex + batchSize); currentIndex += batchSize; // 执行当前批次的所有请求 return Promise.all( batchItems.map(item => ajaxUploadTrackable(item) .then(res => ({ success: true, data: res })) .catch(err => ({ success: false, error: err })) ) ).then(batchResults => { allResults = allResults.concat(batchResults); return processNextBatch(); }); } return processNextBatch(); } // 使用示例:每次发起6个请求 batchRequest(List, 6).then(results => { results.forEach((result, idx) => { if (result.success) { console.log(`第${idx+1}个请求成功:`, result.data); } else { console.log(`第${idx+1}个请求失败:`, result.error); } }); });
2. 合理设置AJAX超时时间
确保你的ajaxUploadTrackable方法设置了足够长的超时时间,给排队的请求留出执行空间:
function ajaxUploadTrackable(item) { return $.ajax({ url: '你的接口地址', method: 'POST', data: item, timeout: 30000, // 设置30秒超时(可根据实际场景调整) // 其他AJAX配置... }); }
3. 用Promise.allSettled替代$.when(ES6环境适用)
如果项目支持ES6 Promise,可以把jQuery的Deferred对象转换为Promise,然后用Promise.allSettled处理所有请求结果(不管成功还是失败):
// 把jQuery请求转为ES6 Promise const requestPromises = List.map(item => ajaxUploadTrackable(item).promise()); Promise.allSettled(requestPromises).then(results => { results.forEach((result, idx) => { if (result.status === 'fulfilled') { console.log(`请求${idx+1}成功:`, result.value); } else { console.log(`请求${idx+1}失败:`, result.reason); } }); });
4. 检查服务器端配置
联系后端开发人员,确认服务器是否有请求频率限制,是否需要调整限流规则,或者是否支持HTTP/2协议来提升并发处理能力。
内容的提问来源于stack exchange,提问作者happenask
相关产品推荐
相关产品推荐

