NestJS/TypeScript多异步函数Try Catch优化:不中断流程
NestJS/TypeScript 异步流程步骤的优雅错误处理优化
问题背景
你有一个流程控制方法my_flow_implementation,在checkIfCanbeDeleted验证通过后,需要依次执行多个异步步骤(step1_execution到stepN_execution)。每个步骤可能执行失败,需针对错误类型单独处理且不中断后续流程,但嵌套try-catch的写法冗余且不优雅,需要更简洁的实现方式。
方案1:封装通用执行函数
把重复的try-catch逻辑抽成一个通用工具函数,每个步骤只需要传入执行逻辑和对应的错误处理逻辑即可:
// 通用步骤执行函数,封装错误处理逻辑 async function executeStep<T>( stepFn: () => Promise<T>, errorHandler: (error: unknown) => void ): Promise<T | null> { try { return await stepFn(); } catch (error) { errorHandler(error); return null; // 根据业务需求返回默认值或null } } // 优化后的流程方法 async my_flow_implementation(...) { const checkIfCanbeDeleted = some_method(...); if (checkIfCanbeDeleted) { const step1_status = await executeStep( () => step1_execution(...), (error) => { // 针对step1的错误做处理,比如日志、数据回滚等 console.error('step1执行失败:', error); } ); const step2_status = await executeStep( () => step2_execution(...), (error) => { console.error('step2执行失败:', error); // 这里可以添加step2专属的错误处理逻辑 } ); // ... 后续步骤依此类推 const stepn_status = await executeStep( () => stepN_execution(...), (error) => { console.error('stepN执行失败:', error); } ); } }
这种写法把重复的错误捕获逻辑抽离,每个步骤只需要关注自身的执行和错误处理,代码结构更清晰。
方案2:步骤配置化+遍历执行
如果步骤数量较多,可以把每个步骤的执行逻辑和错误处理配置成数组,通过循环遍历执行,后续新增步骤只需要在数组中添加配置项即可:
async my_flow_implementation(...) { const checkIfCanbeDeleted = some_method(...); if (checkIfCanbeDeleted) { // 定义所有步骤的配置:执行函数 + 错误处理函数 const steps = [ { execute: () => step1_execution(...), handleError: (error: unknown) => console.error('step1失败:', error) }, { execute: () => step2_execution(...), handleError: (error: unknown) => { console.error('step2失败:', error); // step2的特殊错误处理,比如发送告警 } }, // ... 新增步骤直接在这里添加配置 { execute: () => stepN_execution(...), handleError: (error: unknown) => console.error('stepN失败:', error) } ]; // 遍历执行所有步骤,收集结果 const stepStatuses = []; for (const step of steps) { const status = await executeStep(step.execute, step.handleError); stepStatuses.push(status); } // 按需解构获取每个步骤的结果 const [step1_status, step2_status, ...restStatuses] = stepStatuses; } } // 复用方案1中的executeStep通用函数 async function executeStep<T>( stepFn: () => Promise<T>, errorHandler: (error: unknown) => void ): Promise<T | null> { try { return await stepFn(); } catch (error) { errorHandler(error); return null; } }
这种方式扩展性更强,流程逻辑和步骤实现分离,维护起来更方便。
方案3:默认错误处理简化代码
如果大部分步骤的错误处理逻辑有共性(比如只是记录日志),可以给通用函数添加默认错误处理,特殊步骤再传入自定义逻辑:
async function executeStep<T>( stepFn: () => Promise<T>, errorHandler?: (error: unknown) => void ): Promise<T | null> { try { return await stepFn(); } catch (error) { // 默认错误处理:通用日志记录 console.error('步骤执行失败:', error); // 如果有自定义错误处理,优先执行 errorHandler?.(error); return null; } } // 使用示例 async my_flow_implementation(...) { const checkIfCanbeDeleted = some_method(...); if (checkIfCanbeDeleted) { // 普通步骤用默认错误处理 const step1_status = await executeStep(() => step1_execution(...)); // 特殊步骤传入自定义错误处理 const step2_status = await executeStep( () => step2_execution(...), (error) => { // 这里写step2专属的错误处理,比如数据库回滚、发送通知 } ); // ... 后续步骤 } }
内容的提问来源于stack exchange,提问作者Pradip
相关产品推荐
相关产品推荐

