TypeScript通用失败Promise重试包装器修复及优化咨询
修复后的通用Promise重试包装器
原包装器的核心错误点:
- 参数传递错误:调用目标函数
fn时使用fn(args),args是数组会被作为单个参数传入,导致目标函数参数不匹配直接触发reject,正确做法是用扩展运算符fn(...args)展开数组为单个参数。 - 递归调用错误:递归时误用了不存在的
this.errorWrapper,应直接调用当前函数promiseRepeatWrapper,且传递参数时需用...args保持参数展开,避免数组被当作单个参数传递。 - this指向冗余:普通函数中的
this在全局调用场景下无意义,直接调用函数即可,无需依赖this。
修复后的代码:
// 补充sleep函数实现(原代码中未给出,需确保存在) function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } function promiseRepeatWrapper(fn: (...args: any[]) => Promise<any>, n: number = 0, ...args: any[]) { return new Promise((resolve) => { fn(...args).then((r) => { resolve(r); }).catch(() => { if (n < 3) { console.log("Partial error: " + n); sleep(1000).then(() => { resolve(promiseRepeatWrapper(fn, n + 1, ...args)); }); } else { resolve(undefined); } }); }); }
Promise重试模式的错误处理改进建议
保留错误详情:当前实现忽略了错误具体信息,建议在catch中捕获错误对象并记录,方便排查问题:
.catch((error) => { console.log(`Partial error ${n}:`, error); // 后续重试逻辑 })配置化重试规则:将重试次数、间隔时间改为可配置参数,提升包装器通用性:
function promiseRepeatWrapper( fn: (...args: any[]) => Promise<any>, maxRetries: number = 3, retryDelay: number = 1000, n: number = 0, ...args: any[] ) { // 逻辑中用maxRetries代替硬编码的3,retryDelay代替1000 }指数退避策略:对不稳定API采用指数退避(如第1次等1秒,第2次2秒,第3次4秒),避免短时间重复请求加重服务端压力:
const delay = retryDelay * Math.pow(2, n); sleep(delay).then(/* 重试逻辑 */);过滤可重试错误:并非所有错误都适合重试(如参数错误、401权限错误),允许传入错误过滤函数,仅对特定错误重试:
function promiseRepeatWrapper( fn: (...args: any[]) => Promise<any>, shouldRetry: (error: any) => boolean = () => true, maxRetries: number = 3, retryDelay: number = 1000, n: number = 0, ...args: any[] ) { // catch中添加判断: if (n < maxRetries && shouldRetry(error)) { // 执行重试 } else { resolve(undefined); } }用async/await简化代码:替代嵌套Promise,提升代码可读性:
async function promiseRepeatWrapper( fn: (...args: any[]) => Promise<any>, maxRetries: number = 3, retryDelay: number = 1000, n: number = 0, ...args: any[] ) { try { const result = await fn(...args); return result; } catch (error) { if (n < maxRetries) { console.log(`Partial error ${n}:`, error); await sleep(retryDelay * Math.pow(2, n)); return promiseRepeatWrapper(fn, maxRetries, retryDelay, n + 1, ...args); } return undefined; } }优化原fetchAPI的错误捕获:原fetchAPI中的同步try/catch无法捕获异步错误,应改为直接链式捕获:
function fetchAPI(arg1: number, arg2: number, arg3: string) { return myFetchFunction(arg1, arg2, arg3).then((r: any) => { if (!r) { throw new Error("Error 01"); } return r; }).catch(() => { throw new Error("Error 01"); }); }
内容的提问来源于stack exchange,提问作者Riccardo Perego
相关产品推荐
相关产品推荐

