React Native调用API报JSON Parse error 咨询最优请求重试方案
你当前的无限制递归重试方案存在两个核心缺陷:
- 最坏情况下会无限触发请求,时间复杂度为无穷大,既会造成客户端资源浪费,也可能触发服务端限流策略
- 无延迟的连续重试对瞬时故障的修复作用有限,大概率会连续触发相同错误
优化建议
- 增加最大重试次数限制:设置重试上限(推荐3~5次),超过阈值后终止重试并抛出明确错误,避免无限循环
- 增加指数退避机制:每次重试前增加递增的等待时长,例如第一次重试间隔1s、第二次2s、第三次4s,降低服务端压力的同时,大幅提升瞬时网络波动、服务端限流场景下的重试成功率
- 提前校验响应格式:你遇到的JSON解析错误本质是服务端返回了非JSON格式的响应(通常是限流、服务异常时返回的HTML错误页,开头包含"You"字符才会触发对应解析错误),可以先读取响应文本、校验格式合法性后再执行JSON序列化,减少无意义的重试
- 重试逻辑内聚到请求函数:把重试逻辑封装在请求工具内部,调用层无需感知重试逻辑,复用性更强
改造后代码示例
// 封装通用重试工具函数 const retryRequest = async (requestFn, maxRetries = 3, delay = 1000) => { try { return await requestFn(); } catch (err) { if (maxRetries <= 0) throw err; // 指数退避等待 await new Promise(resolve => setTimeout(resolve, delay)); return retryRequest(requestFn, maxRetries - 1, delay * 2); } } export async function fetchAllCoinsPromise() { const apiCall = await fetch('https://api.coincap.io/v2/assets'); // 先校验响应格式合法性 const contentType = apiCall.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { const rawText = await apiCall.text(); throw new Error(`非JSON响应: ${rawText.slice(0, 100)}`); } const jsonResult = await apiCall.json(); return jsonResult; } // 调用方式 const fetchCoins = async () => { try { const res = await retryRequest(fetchAllCoinsPromise); console.log(111, res); } catch (err) { console.log('最终请求失败', err); } }
内容的提问来源于stack exchange,提问作者user14587589
相关产品推荐
相关产品推荐

