如何使用Promise.allSettled替代try/catch捕获多异步请求错误
实现方案
用Promise.allSettled的核心逻辑是利用它返回的结果和传入Promise的顺序严格对应的特性,分别处理每个请求的成功/失败状态,既可以收集所有失败请求的错误信息,也能按索引或映射关系取出成功请求的返回值。相比原来逐个写try/catch的串行写法,还能实现异步请求并行执行,缩短整体接口耗时。
基础版本实现(适合请求数量少的场景)
直接按顺序传入请求,按索引取结果即可,代码如下:
async createProduct(): Promise<ProductObject> { // 按业务需要的顺序定义异步请求列表 const requestList = [ getProductType(), getColor(), // 新增校验请求直接往数组里加即可 ] // 等待所有请求执行完毕,不受单个失败影响 const settledResults = await Promise.allSettled(requestList) const errors: string[] = [] // 按顺序解构对应请求的结果 const [productTypeResult, colorResult] = settledResults // 逐个处理请求状态 if (productTypeResult.status === 'rejected') { errors.push(productTypeResult.reason as string) } if (colorResult.status === 'rejected') { errors.push(colorResult.reason as string) } // 存在错误直接抛出所有错误信息 if (errors.length > 0) { throw new Error(errors.join(',')) } // 所有请求成功,取出返回值供后续逻辑使用 const productType = productTypeResult.value const color = colorResult.value // 原有创建产品的业务逻辑 // ... return product_object }
通用封装版本(适合请求数量多的场景)
如果后续会加很多校验请求,可以封装一个通用处理函数,避免重复写状态判断逻辑:
// 通用处理工具函数,可全局复用 function handleBatchRequest<T>(requests: Array<{ name: string; task: Promise<T> }>) { return Promise.allSettled(requests.map(item => item.task)).then(results => { const errors: string[] = [] const successData: Record<string, T> = {} results.forEach((result, index) => { const { name } = requests[index] if (result.status === 'rejected') { errors.push(result.reason as string) } else { successData[name] = result.value } }) return { errors, successData } }) } // 业务中使用 async createProduct(): Promise<ProductObject> { const { errors, successData } = await handleBatchRequest([ { name: 'productType', task: getProductType() }, { name: 'color', task: getColor() }, // 新增请求只需要加一行配置即可 ]) if (errors.length > 0) { throw new Error(errors.join(',')) } // 直接从对象中取对应返回值,不需要记索引 const { productType, color } = successData // 原有业务逻辑 // ... return product_object }
注意事项
- 需要返回未找到的ID数组的话,只需要在
getProductType、getColor这类请求抛出错误时,把对应未找到的ID作为错误reason抛出即可,收集到的errors数组就是所有未找到的ID。 - TS原生支持
PromiseSettledResult类型,不需要额外定义类型声明,类型推导可以正常工作,适配NestJS + TypeScript技术栈。 - 该方案是并行发起所有请求,比原来逐个await的串行写法耗时更短,性能更好。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

