传入多个Deferred对象至jQuery.when时遇到的问题
处理jQuery.when()中部分成功的请求
你说得对,jQuery.when()的默认行为确实是只要有一个Deferred被拒绝,就立刻触发失败回调,没法直接拿到所有成功的结果。要实现只保留成功请求的需求,我们可以换个思路——先给每个请求单独处理失败情况,让它们不会触发全局的失败,然后再收集所有结果筛选成功的。
具体可以这么做:
- 给每个
$.get()请求添加.fail()回调,在失败时返回一个已解决的Deferred(可以用$.Deferred().resolve()),这样不管请求成功还是失败,每个请求都会返回一个已解决的Promise,不会让$.when()直接进入失败状态。 - 然后在
$.when()的.then()回调里,拿到所有请求的结果,筛选出那些实际成功的请求数据。
下面是具体的代码示例:
// 先把所有请求包装一下,确保每个请求都不会被拒绝 const requests = [ $.get('API string 1').fail(() => $.Deferred().resolve(null)), $.get('API string 2').fail(() => $.Deferred().resolve(null)), $.get('API string 3').fail(() => $.Deferred().resolve(null)), $.get('API string 4').fail(() => $.Deferred().resolve(null)), $.get('API string 5').fail(() => $.Deferred().resolve(null)) ]; // 用$.when处理所有包装后的请求 $.when(...requests).then(function(...results) { // 筛选出成功的结果:成功的请求会返回[data, statusText, jqXHR],失败的是[null] const successfulResults = results.filter(result => result[0] !== null); // 如果你需要单独的jqXHR对象,也可以从结果里提取 const successfulJqXHRs = successfulResults.map(result => result[2]); // 这里可以返回处理后的Promise,或者直接处理成功结果 return $.Deferred().resolve(successfulResults).promise(); });
另外还有一种更简洁的方式,利用Promise.allSettled()(不过注意jQuery 3.0+才支持和原生Promise的互操作),如果你的项目里jQuery版本够新,也可以这么写:
// 把jQuery的Deferred转换成原生Promise const nativeRequests = [ $.get('API string 1').promise(), $.get('API string 2').promise(), $.get('API string 3').promise(), $.get('API string 4').promise(), $.get('API string 5').promise() ]; // 使用Promise.allSettled等待所有请求完成 Promise.allSettled(nativeRequests).then(results => { // 筛选出成功的结果 const successfulResults = results .filter(result => result.status === 'fulfilled') .map(result => result.value); // 同样可以提取jqXHR,这里value就是[data, statusText, jqXHR] const successfulJqXHRs = successfulResults.map(result => result[2]); // 返回处理后的Promise return Promise.resolve(successfulResults); });
解释一下两种方式的区别:
- 第一种方式兼容所有jQuery版本,通过包装每个请求确保
$.when()能等待所有请求完成,不管成功失败。 - 第二种方式更现代,利用原生Promise的
allSettledAPI,代码更简洁,但需要jQuery 3.0及以上版本,因为从这个版本开始jQuery的Promise实现了原生Promise的接口。
这样你就能轻松拿到所有成功的请求结果,并且可以返回一个包含这些结果的Promise供后续使用啦。
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

