通用Promise指数退避重试函数问题:后续重试成功无输出求助
解决Promise重试函数的两个核心问题
我来帮你分析下代码里的问题,以及对应的修复方案:
问题1:后续重试resolve时无法输出结果
你当前的代码里,当第一次调用func失败后,虽然递归调用了retry,但这个新创建的Promise的结果完全没有和外层Promise的resolve/reject挂钩。外层Promise只在第一次func成功时才会触发resolve,后续重试的Promise结果无法传递到外层,导致外层Promise一直处于pending状态,自然不会触发.then(r => console.log(r))回调。
问题2:弃用警告
这个警告大概率来自setTimeout里的传统函数写法,加上递归时没有正确传递错误结果,在一些环境(比如Node.js新版本)中会触发相关提示,换成箭头函数并正确处理结果传递后就能解决。
修复后的代码
function retry(func, maxAttempts, delay) { console.log(`剩余重试次数: ${maxAttempts}`); return new Promise((resolve, reject) => { func() .then(resolve) // 直接传递resolve,简化写法 .catch(err => { if (maxAttempts === 0) { reject(err); // 用尽所有次数,抛出最终错误 } else { // 使用箭头函数避免上下文问题,同时将递归retry的结果绑定到外层Promise setTimeout(() => { retry(func, maxAttempts - 1, delay * 2) .then(resolve) .catch(reject); }, delay); } }); }); } const promise = retry(function () { return new Promise((resolve, reject) => { const rand = Math.random(); if (rand >= 0.8) { resolve('hey'); } else { reject(new Error('oh noes')); } }); }, 5, 100); promise.then(r => console.log('成功结果:', r)).catch(err => console.log('最终错误:', err));
关键修改点说明
- 绑定递归Promise的结果:在
setTimeout里,递归调用retry后,通过.then(resolve)和.catch(reject)把新Promise的结果传递给外层Promise的resolve/reject,这样无论第几次重试成功,外层Promise都能正确接收结果。 - 避免修改外层变量:用
maxAttempts - 1代替--maxAttempts,防止意外修改外层函数的参数变量,避免潜在的逻辑错误。 - 简化resolve写法:直接把
resolve作为.then的回调,替代原来的r => resolve(r),代码更简洁。 - 箭头函数替代传统function:解决可能的上下文绑定问题,同时消除相关弃用警告。
这样修改后,无论是第一次调用成功,还是后续重试成功,都能正确输出'hey';错误时也会正确传递最终的错误信息,同时弃用警告也会消失。
内容的提问来源于stack exchange,提问作者Mr. Ant
相关产品推荐
相关产品推荐

