React Native Android端fetch无返回无报错请求挂起问题咨询
React Native Android 端 fetch/XMLHttpRequest 请求挂起无响应解决方法
问题根因说明
你遇到的请求无报错、无响应、await 永久卡住的问题,在 RN 0.68 + Expo 45 搭配 tfjs 的项目里非常常见,核心原因基本分两类:一是 Android 环境下本地服务地址配置错误,二是第三方依赖注入的 polyfill 破坏了 RN 原生的网络 API 和事件循环逻辑。
分步解决
1. 先修正本地服务访问地址
Android 环境的网络隔离和桌面端不同,localhost 默认指向设备/模拟器自身,不是你运行 Metro 的开发机:
- 用官方 Android 模拟器调试的话,把请求地址里的
localhost换成10.0.2.2,这是模拟器专门映射到开发机回环地址的固定IP - 用真机调试的话,把地址换成开发机在当前局域网的IPv4地址,同时保证手机和电脑连接同一个WiFi
- 执行端口转发命令打通链路:终端运行
adb reverse tcp:8081 tcp:8081,把设备的8081端口直接映射到开发机的8081端口,避免地址路由问题。
2. 修复 polyfill 冲突(90% 概率是这个问题)
看你的依赖列表里装了 @tensorflow/tfjs-react-native 和 react-native-polyfill-globals,这两个依赖会在导入时自动覆写全局的 fetch、XMLHttpRequest、Promise 实现,和 RN 0.68 自带的 JSC/Hermes 引擎兼容性极差,会直接导致网络请求发出去后,回调永远无法被JS线程调度:
- 先检查入口文件(
index.js/App.js),把类似import 'react-native-polyfill-globals/auto'这类全量注入polyfill的代码全部注释掉,RN 0.68 已经自带符合标准的 fetch、Encoding API 实现,不需要额外引入第三方polyfill - 如果必须使用 tfjs,不要用全量导入的方式,避免触发它自带的polyfill注入逻辑,改成手动注册平台:
import { setPlatform } from '@tensorflow/tfjs-core'; import { PlatformReactNative } from '@tensorflow/tfjs-react-native/dist/platform_react_native'; setPlatform(new PlatformReactNative());
- 移除冗余的
text-encoding、whatwg-fetch这类重复实现Web API的依赖,这类依赖的旧版本会直接破坏RN的事件循环队列,导致异步回调永远不执行。
3. 排除JS线程阻塞问题
如果改完上面的配置还是有问题,检查你的代码执行逻辑:
- 不要在发起请求的同步执行流里插入CPU密集型任务(比如tfjs模型初始化、大文件同步读写、大量数据循环计算),这类任务会占满JS线程,网络请求的回调没有机会被执行,就会表现为永久挂起
- 先写个最小测试用例验证网络链路正常,把请求放到按钮点击事件里触发,排除其他代码的干扰:
<Button title="测试网络请求" onPress={async () => { console.log('请求发起'); try { const res = await fetch('http://10.0.2.2:8081/assets/src/...'); console.log('请求成功', await res.text()); } catch (err) { console.log('请求失败', err); } }} />
4. 补全明文流量配置
确认你之前加的 cleartext 配置位置正确:
android:usesCleartextTraffic="true"必须写在AndroidManifest.xml的<application>标签上,写在manifest、activity标签上不会生效- 针对Android 9+系统,额外加网络安全配置放行本地地址:在
android/app/src/main/res/xml/目录下新建network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">10.0.2.2</domain> <domain includeSubdomains="true">localhost</domain> </domain-config> </network-security-config>
然后在 <application> 标签上添加属性 android:networkSecurityConfig="@xml/network_security_config" 即可。
内容的提问来源于stack exchange,提问作者Slice
相关产品推荐
相关产品推荐

