为何Promise.catch无法捕获错误?重试函数异常排查
修复你的重试函数问题
问题根源
fetch 只有在网络层面出错(比如断网、DNS解析失败)时才会让Promise进入reject状态。像429这类HTTP错误状态码,fetch 会返回一个状态为resolve的Promise,只是响应对象的ok属性为false。这就导致你的代码里catch分支完全没执行,控制台显示的429是浏览器自带的请求日志,不是你代码中console.log(err)的输出,自然也不会触发重试逻辑。
修复方案
方案1:让重试函数适配fetch的特性
修改重试函数,在then分支里判断响应状态,异常时主动抛出错误,触发重试:
export function retry(fn: Function, params: any, times = 1e9 + 7) { return new Promise((resolve, reject) => { const attempt = () => { fn(params) .then((res: Response) => { // 检查HTTP响应是否正常,不正常则抛出错误进入catch if (!res.ok) { throw new Error(`请求失败:${res.status} ${res.statusText}`); } resolve(res); }) .catch((err: Error) => { console.log(err.message); // 现在能正常输出错误信息 times-- > 0 ? attempt() : reject("重试次数耗尽,请求最终失败"); }); }; attempt(); }); }
方案2:封装fetch,让重试函数保持通用
如果你希望重试函数不耦合fetch的逻辑,可以提前包装fetch,让它在HTTP错误时抛出异常:
// 包装fetch,处理HTTP错误 const safeFetch = async (url: string) => { const res = await fetch(url); if (!res.ok) { throw new Error(`请求失败:${res.status} ${res.statusText}`); } return res; }; // 调用重试函数 const res = await retry(safeFetch, url) as Response;
额外优化(可选)
如果需要支持多参数的函数(比如fetch需要配置项),可以把参数改成数组,用扩展运算符传递:
export function retry(fn: Function, args: any[], times = 1e9 + 7) { return new Promise((resolve, reject) => { const attempt = () => { fn(...args) .then((res: Response) => { if (!res.ok) throw new Error(`请求失败:${res.status} ${res.statusText}`); resolve(res); }) .catch((err: Error) => { console.log(err.message); times-- > 0 ? attempt() : reject("重试耗尽"); }); }; attempt(); }); } // 调用示例:带配置项的fetch const res = await retry(fetch, [url, { method: 'POST', body: data }]) as Response;
内容的提问来源于stack exchange,提问作者SNORLAX
相关产品推荐
相关产品推荐

