使用async/await并发请求不丢结果,Promise.all失败如何保留其余结果?
如何用async/await发送并发请求且不丢失部分结果?
这个问题问得好!Promise.all的“全有或全无”特性确实会在单个请求失败时直接抛出错误,导致我们拿不到其他已经成功完成的请求结果,但完全不用退回到then().catch()的老语法,用纯async/await就能完美解决核心问题——让每个异步请求的Promise都始终处于fulfilled状态,哪怕它实际执行失败了。
核心思路
Promise.all只有当所有传入的Promise都fulfilled时才会返回成功结果,只要有一个rejected,它就会立即触发reject。所以我们要做的是给每个请求单独做错误兜底,让每个请求的Promise最终都返回一个包含“成功/失败状态”的对象,而不是直接reject。这样Promise.all就能收集到所有请求的结果,不管单个请求是否成功。
实现方案1:用包装函数统一处理(推荐,可复用)
我们可以写一个通用的包装函数,把任意异步请求(或async函数)包裹起来,用try/catch捕获错误,返回统一格式的结果对象:
// 模拟一个可能失败的异步请求 async function fetchResource(id) { if (id === 3) throw new Error(`资源 ${id} 不存在`); return { id, content: `资源内容 ${id}` }; } // 通用包装函数:处理单个请求的成功/失败 async function wrapAsyncRequest(requestFn) { try { const data = await requestFn(); return { success: true, data }; } catch (error) { // 这里可以根据需求处理错误,比如只返回错误信息,或者保留完整Error对象 return { success: false, error: error.message }; } } // 并发请求的主函数 async function fetchAllResources() { // 准备所有要发送的请求,用包装函数包裹 const requestList = [ wrapAsyncRequest(() => fetchResource(1)), wrapAsyncRequest(() => fetchResource(2)), wrapAsyncRequest(() => fetchResource(3)) ]; // 用Promise.all并发执行,await获取所有结果 const allResults = await Promise.all(requestList); // 按需分离成功和失败的结果 const successfulResults = allResults.filter(item => item.success).map(item => item.data); const failedResults = allResults.filter(item => !item.success).map(item => item.error); console.log("成功获取的资源:", successfulResults); console.log("失败的请求:", failedResults); } fetchAllResources();
实现方案2:内联async函数(适合少量请求)
如果只是偶尔处理几个请求,不想单独写包装函数,也可以直接在Promise.all的数组里写内联的async函数,同样用try/catch兜底:
async function fetchAllResources() { const allResults = await Promise.all([ (async () => { try { return { success: true, data: await fetchResource(1) }; } catch (err) { return { success: false, error: err.message }; } })(), (async () => { try { return { success: true, data: await fetchResource(2) }; } catch (err) { return { success: false, error: err.message }; } })(), (async () => { try { return { success: true, data: await fetchResource(3) }; } catch (err) { return { success: false, error: err.message }; } })() ]); // 后续处理和方案1一致 const successfulResults = allResults.filter(item => item.success).map(item => item.data); const failedResults = allResults.filter(item => !item.success).map(item => item.error); console.log("成功获取的资源:", successfulResults); console.log("失败的请求:", failedResults); }
为什么这两种方案都不用then/catch?
因为我们全程用async/await配合try/catch来处理错误,完全没有依赖then()和catch()链式调用的语法,既保持了代码的可读性,又解决了Promise.all丢结果的问题。
内容的提问来源于stack exchange,提问作者Carter
相关产品推荐
相关产品推荐

