React Native生产环境随机报TypeError: Network request failed求助
问题根因与修复方案
现有代码存在的核心问题
- 重试逻辑存在漏洞:当前仅对第一次网络错误做1次重试,若第二次请求仍然失败,直接抛出错误无兜底;且未区分请求类型,POST/PUT等非幂等请求重试可能导致重复提交等业务问题。
- 缺少请求超时控制:原生
fetch默认无超时限制,网络波动、服务端临时响应慢超过系统默认阈值时,会直接抛出TypeError: Network request failed。 - 网络判断逻辑不可靠:
NetInfo.fetch()仅能判断设备是否接入网络,无法判断网络是否能正常访问你的API服务,比如连接了无外网的WiFi、DNS临时解析失败时,NetInfo会返回已连接,但实际请求会失败,这也是你本地关闭API服务可复现问题的原因。 - 未处理请求头非法字符风险:请求头中直接带入路由名
currentroute,若路由名存在特殊字符、中文,未做编码的情况下可能被代理或服务器拦截,导致随机请求失败。 - 无网络时返回值不统一:
checkNetwork返回false时直接returnundefined,上层业务若无适配处理也可能引发预期外的错误。
代码修复方案
1. 新增超时控制工具函数
// 新增,默认超时时间15s,可根据业务调整 const fetchWithTimeout = (url, config, timeout = 15000) => { return Promise.race([ fetch(url, config), new Promise((_, reject) => setTimeout(() => reject(new TypeError('Network request failed: timeout')), timeout) ) ]) }
2. 优化重试逻辑
// execute方法内的请求逻辑替换为以下内容 const MAX_RETRY_COUNT = 2; // 最多重试2次,加上第一次请求总共3次 let retryCount = 0; let response; while (retryCount <= MAX_RETRY_COUNT) { try { // 替换原有fetch为带超时的方法 response = await fetchWithTimeout(url, config); break; } catch (e) { // 仅GET请求、网络错误、还有重试次数的时候才重试 if ( e?.toString().includes('Network request failed') && method.toUpperCase() === 'GET' && retryCount < MAX_RETRY_COUNT ) { // 指数退避延迟,每次重试间隔翻倍,减少服务端压力 await new Promise(res => setTimeout(res, 250 * Math.pow(2, retryCount))); retryCount++; continue; } throw e; } }
3. 优化请求头编码
// headers中的currentroute做编码处理 currentroute: encodeURIComponent(this.navigation?.getCurrentRoute?.()?.name || ''),
4. 统一无网络时的返回值
const canFetch = await checkNetwork(); if (!canFetch) { return { ok: false, error: '当前网络不可用,请检查网络设置后重试' }; }
其他排查方向
如果修改代码后问题仍存在,可以按以下方向排查:
- 检查SSL证书配置:确认证书是否在所有目标设备系统版本上受信任,安卓7以下、iOS12以下对部分新CA证书支持不全,会导致SSL握手失败抛出网络错误。
- 排查DNS解析问题:部分地区运营商DNS解析不稳定,可以考虑集成HTTPDNS服务,提前解析域名IP,避免DNS解析失败。
- 收集错误维度信息:在Sentry的上报信息中补充设备系统版本、运营商、网络类型(WiFi/4G/5G),看错误是否集中在特定场景,缩小排查范围。
- 检查iOS ATS配置/安卓明文请求限制:确认iOS生产环境ATS规则未限制域名访问,安卓如果使用HTTP请求已配置
android:usesCleartextTraffic="true"。
内容的提问来源于stack exchange,提问作者arnaudambro
相关产品推荐
相关产品推荐

