jQuery Promise:部分JSON获取失败时仍触发done方法的实现问询
解决jQuery Promise部分请求失败仍触发done的问题
这个问题我之前也碰到过——jQuery的$.when是「失败即全败」的逻辑:只要其中一个Promise被rejected,整个组合就会直接跳去fail回调,完全忽略其他成功的请求。要实现「部分JSON缺失/请求失败仍触发done」的效果,核心是把每个单独的请求都包装成永远不会reject的Promise,不管它成功还是失败,都用resolved的状态把结果(或者错误标识)传递下去。
具体修改方案
1. 先写一个请求包装函数
这个函数会帮我们把$.getJSON的请求转换成「总是resolve」的Promise,成功时返回JSON数据,失败时返回null(你也可以换成自定义的错误标识):
function getSafeJson(url) { return $.getJSON(url) .then( // 请求成功:直接返回获取到的JSON数据 (data) => data, // 请求失败:返回null标记该请求未获取到数据 () => null ); }
2. 重构原有的$.when调用
把原来的条件判断逻辑替换成包装后的请求,同时对不需要发起请求的项,用$.when(null)生成一个已resolve的Promise(代替原来的null,保证统一的Promise格式):
$.when( arrayResults[0] ? getSafeJson("url") : $.when(null), arrayResults[1] ? getSafeJson("url") : $.when(null), arrayResults[2] ? getSafeJson("url") : $.when(null) ).done(function(result0, result1, result2) { // 在这里可以拿到每个请求的结果:成功的是JSON数据,失败/未发起的是null console.log('第一个请求结果:', result0); console.log('第二个请求结果:', result1); console.log('第三个请求结果:', result2); // 示例:过滤掉无效结果,只处理成功获取到的数据 const validData = [result0, result1, result2].filter(res => res !== null); // 继续你的业务逻辑... }).fail(function() { // 现在这个fail回调几乎不会触发了(除非出现极端环境错误),可以根据需求保留或删除 console.log('极端错误触发'); });
更灵活的写法(适配动态长度的arrayResults)
如果arrayResults的长度可能变化,推荐用数组映射的方式生成Promise数组,再用$.when.apply来组合:
// 把arrayResults转换成全是resolve状态的Promise数组 const promiseList = arrayResults.map(item => { if (!item) return $.when(null); return $.getJSON("url").then(data => data, () => null); }); // 组合所有Promise并处理结果 $.when.apply($, promiseList).done(function() { // arguments会按顺序返回每个Promise的结果,转成数组更方便处理 const allResults = Array.from(arguments); console.log('所有请求结果:', allResults); // 过滤有效数据 const validData = allResults.filter(res => res !== null); // 业务逻辑... });
原理说明
通过包装每个请求,我们把原本可能reject的Promise都改成了resolve状态——不管请求成功还是失败,都会向$.when传递一个结果值。这样$.when会等待所有请求完成后进入done回调,你可以在回调里自行判断哪些数据有效,哪些缺失,完全掌控后续逻辑。
内容的提问来源于stack exchange,提问作者Okami Okami
相关产品推荐
相关产品推荐

