JavaScript如何实现await异步函数超时等待重试与错误处理
原有代码的核心问题
- 未对异步函数
update()使用await:异步函数返回Promise对象,不添加await时,函数内部抛出的错误不会被外层try/catch捕获,代码会直接执行success = true,循环直接终止,完全达不到重试效果。 - 原生
setTimeout是非阻塞API:空回调的setTimeout不会暂停循环执行,while循环会瞬间跑完无数轮,造成CPU占满的死循环,根本等不到10秒的延迟。
可直接运行的实现代码
首先实现可被await的延迟工具函数,再按伪代码逻辑写重试流程:
// 封装等待指定毫秒的工具函数 const sleep = (waitMs) => new Promise(resolve => setTimeout(resolve, waitMs)); async function executeWithRetry() { // 无限循环直到执行成功 while (true) { try { // 等待update执行完成,错误会被catch块捕获 await update(); // 无报错则跳出循环,执行后续逻辑 break; } catch (error) { // 此处可添加自定义错误上报、日志逻辑 console.error('update执行失败,10秒后重试', error); // 等待10秒后进入下一轮循环 await sleep(10000); } } // === 以下是伪代码line05对应的后续业务逻辑 === console.log('update执行成功,继续后续流程') } // 启动执行 executeWithRetry();
实现原理解释
- 异步错误捕获逻辑:
async/await是Promise的语法糖,只有await一个Promise时,Promise的reject状态才会被转化为可被try/catch捕获的同步抛出错误。如果省略await,update()会立刻返回pending状态的Promise,外层try块会直接判定执行完成,后续Promise抛出的错误会变成未捕获的Promise错误,重试逻辑完全失效。 - 阻塞等待实现:JS本身没有同步休眠的API,直接调用setTimeout只会把回调加入事件循环的宏任务队列,当前执行栈的代码(也就是while循环)会持续空转。把setTimeout封装为返回Promise的sleep函数后,配合await会暂停当前async函数的执行,等10秒后Promise状态变为fulfilled才会继续下一轮重试,完全匹配伪代码的等待要求。
- 循环控制逻辑:使用
while(true)构造无限循环,只有update执行成功走到break语句时才会退出循环,完全对应伪代码里「失败则回到第一步重试,成功则继续执行」的流程。
可选优化:增加最大重试次数
如果不希望无限重试,可以加重试计数,超过次数后直接抛出错误终止流程:
async function executeWithRetry(maxRetryTimes = 5) { let currentRetry = 0; while (currentRetry < maxRetryTimes) { try { await update(); break; } catch (error) { currentRetry++; console.error(`update第${currentRetry}次执行失败`, error); if (currentRetry >= maxRetryTimes) { throw new Error(`连续重试${maxRetryTimes}次后update仍执行失败`); } await sleep(10000); } } // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者Derawi
相关产品推荐
相关产品推荐

