react-native-hiapp网络层深度剖析:50行手写fetch封装Req类的完整实现原理
【免费下载链接】react-native-hiappHiApp written in react-native.项目地址: https://gitcode.com/gh_mirrors/re/react-native-hiapp
react-native-hiapp 是一款用 React Native 编写的仿秒拍社交应用(HiApp)。它没有引入任何第三方网络请求库,整个 App 的请求能力都来自一个约 50 行的手写 fetch 封装——Req 类。本文带你拆解这份 React Native 网络层源码的完整实现原理,新手读完可以直接照搬到自己的项目里。
一、50 行代码,如何撑起整个 App 的信息流?
先给结论:HiApp 里的时间线加载、下拉刷新、分页更多、通讯录、用户登录、动态评论,全部请求都走同一个类,源码只有 App/Network/index.js 这一个文件,全文不到 60 行。
它由 4 个部分组成,各司其职:
| 组件 | 位置 | 职责 |
|---|---|---|
_buildQuery() | App/Network/index.js | 对象 → URL 编码后的 query 串 |
_httpDone()/_httpFail() | App/Network/index.js | HTTP 状态 + 业务错误码双重判定 |
fetch() | App/Network/index.js | 组装请求参数,调用原生 fetch |
get()/post() | App/Network/index.js | 两个快捷方法,减少重复代码 |
📌 对比思路:很多人第一反应是安装 axios。而这个项目证明——只靠 React Native 运行时内置的
fetchAPI,加上不到 50 行封装,就够一个完整社交 App 使用了。这正是这份源码最值得学习的地方。
二、_buildQuery:手写 URL 编码,3 行搞定 query 参数
如果调用时传了query对象,封装会先把它序列化成a=b&c=d这样的字符串,再拼到 URL 后面:
- 对key 和 value 都执行
encodeURIComponent,中文、空格、特殊字符都不会破坏 URL - 用
&连接各键值对 - 结果以
?开头拼接到完整 URL 上
效果相当于标准库的URLSearchParams,但零依赖、跨 iOS / Android 行为完全一致。🔧
三、核心fetch方法:一次请求的完整生命周期
App/Network/index.js 中的fetch()是整个封装的心脏,一次请求按顺序经历 6 步:
- 拼基础地址:
url = this.baseUrl + url,baseUrl 在构造函数里从全局配置读取,调用方只需传相对路径(如/timeline.json) - 拼 query:如果传了
query对象,追加?xxx=yyy - 组装参数:
method默认'GET',并固定credentials: 'same-origin' - 序列化请求体:有
data时执行JSON.stringify放进body - 透传自定义头:传了
headers就原样带过去 - 调用原生 fetch 并分流:
resp.ok(HTTP 2xx)→ 解析 JSON 后进入_httpDone做业务校验- 非 ok → 直接进入
_httpFail返回Promise.reject - 网络层异常(断网等)→ 最外层
.catch统一 reject
也就是说,无论哪一层失败,调用方只需要一个.catch就能兜住所有错误。🛡️
四、双重错误判定:HTTP 成功 ≠ 业务成功
这是新手写 React Native 网络请求最容易踩坑的地方,Req 类的做法很值得抄:
- 传输层错误:靠
resp.ok判断,状态码不是 2xx 直接失败 - 业务层错误:即使 HTTP 返回 200,还会检查 JSON 响应体里的
err_code字段——有值就Promise.reject,没有才放行
if (!res.err_code) { return res } else { return Promise.reject(res) }这样"接口 200 但数据有误"的场景(登录过期、参数错误等)就和真正的网络错误一样,被业务代码统一捕获处理,不用在每个页面里重复判断错误码。
五、单例导出 +@Network别名:一次导入,全局复用
文件最后一行是export default new Req()——导出的不是类,而是唯一实例。全项目共享一个 baseUrl、一套行为,天然单例,也杜绝了各处 new 出来的配置不一致问题。
配套的模块别名定义在 babel.config.js:
'@Network': './App/Network'因此任何页面一行import req from '@Network'就能开用。而 baseUrl 本身收口在 App/Config/index.js 中,devBaseUrl与prodBaseUrl都指向同一份公开托管的 JSON Mock 数据源——这意味着本地运行 HiApp 完全不需要启动后端,请求出去立刻有返回,非常适合作为学习 React Native 网络请求的入门项目。
六、真实调用长什么样?看 Redux Action 里的用法
项目里req.get的调用非常克制,典型示例在 App/Store/Actions/home.js:
return req.get('/timeline.json').then(res => { const data = res.data dispatch(initTimeline(data)) })同一套 API 在项目中共有 5 处消费,覆盖三类典型场景:
- 首屏加载:App/Store/Actions/app.js 中
req.get('/user_login.json')拉取用户信息 - 分页与刷新:App/Store/Actions/home.js 用
/timeline.json、/refresh_timeline.json、/more_timeline.json分别对应加载、下拉刷新、上拉加载更多 - 组件直连:App/Views/Post/index.js 中
req.get('/comments.json')加载动态评论;App/Views/Settings/index.js 也导入了同一个req实例
调用方始终只关心三件事:传什么参数、拿到什么数据、失败怎么办——这正是封装成功的标志。
七、新手可以直接照抄的 4 个设计点
- 配置与实现分离:baseUrl 放在 App/Config/index.js,切换环境只改一处
- 单例导出:
export default new Req(),别名导入,全局行为一致 - 业务错误并入 Promise 链:
err_code校验失败即 reject,.catch一网打尽 - get / post 快捷方法:默认参数 + 覆盖 method,调用方一行搞定
小结:react-native-hiapp 的 Req 类用约 50 行代码回答了"React Native 网络请求最小可用方案"这个问题——query 编码、请求组装、双重错误判定、单例复用,一个都没少,一个多余的依赖都没加。把它读懂,你就掌握了手写 fetch 封装的完整骨架。
【免费下载链接】react-native-hiappHiApp written in react-native.项目地址: https://gitcode.com/gh_mirrors/re/react-native-hiapp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考