uni-app跨端请求封装必须手动封装uni.request,因app端uni.addinterceptor完全无效;需统一处理token异步读取与刷新锁、业务code解析、url协议补全及header大小写等平台差异。

uni-app 的 request 封装不能只靠 uni.addInterceptor,尤其在 App 端基本无效;真正跨端稳定的方案是手动封装 uni.request 函数,并按需补充拦截逻辑。
App 端 uni.addInterceptor('request') 为什么完全不生效
这不是配置问题,而是底层机制限制:iOS 和 Android 原生容器中,uni.request 调用直接走原生网络模块,绕过 JS 层的拦截器注册逻辑。很多团队上线后才发现 App 上 token 没注入、401 不跳转——查日志发现 invoke 根本没执行。
- 仅 H5 和微信/支付宝/字节等小程序支持
uni.addInterceptor,且需注意部分低版本小程序兼容性 - App 端必须把所有请求逻辑收口到自定义函数里,比如
http.get()、http.post() - 若项目已混用拦截器和手动封装,容易出现「H5 正常、App 失效、调试时又好像好了」这类时序型 bug
手动封装 uni.request 必须处理的三个异步陷阱
token 读取、刷新、并发 401 是最常崩掉的三处。同步读 uni.getStorageSync('token') 在冷启动或 store 未初始化时返回空,直接导致 401;多个请求同时失败又各自刷新 token,后端可能返回 429 或状态错乱。
- token 获取应封装为 Promise:优先从 Pinia/Vuex 异步取,fallback 到
uni.getStorageSync,避免时序空值 - 401 刷新必须加锁:
let refreshingPromise = null,后续请求 await 同一个 Promise,而不是重复调refreshToken() - 刷新失败后要重置
refreshingPromise = null,否则后续所有请求永久 pending - 示例片段:
if (res.statusCode === 401) {<br> if (!refreshingPromise) {<br> refreshingPromise = refreshToken();<br> }<br> await refreshingPromise;<br> refreshingPromise = null;<br> // 重发原请求<br>}
后端返回 200 但业务失败?别只看 statusCode
绝大多数真实项目采用「HTTP 状态码恒为 200,靠响应体 code 字段标识业务状态」的约定。如果封装层只判断 res.statusCode === 200 就 resolve,等于把登录过期、权限不足、参数错误全当成成功,前端逻辑会彻底失控。
- 必须解析响应体,检查
res.data.code(常见值如0表示成功,1001表示 token 过期) - 对
code !== 0的情况统一 reject,并在业务层.catch()中处理,而不是在封装层uni.showToast—— 否则无法做条件重试或静默上报 - 建议保留原始响应结构,例如 resolve
{ data: res.data.data, code: res.data.code, msg: res.data.msg },避免信息丢失
uni.request 封装里最容易被忽略的平台差异点
看似简单的 URL 拼接、header 注入,在多端下行为并不一致。比如 H5 支持相对路径,App 端某些安卓机型会自动补 http:// 导致 404;小程序对 header 大小写敏感,authorization 写成小写 iOS 直接丢弃。
- URL 必须显式判断协议:
if (!options.url.startsWith('http')) options.url = BASE_URL + options.url,避免 H5 正常、App 报跨域 - header 键名统一 PascalCase 或全大写(如
Authorization),不要依赖小写 fallback - timeout 在 App 端实测常被系统截断,建议设为
15000以上并配合业务层重试逻辑 - App 端
fail回调中err.errMsg可能是"request:fail timeout"或"request:fail net::ERR_CONNECTION_REFUSED",需正则匹配而非全等判断
真正难的不是写完封装,而是在 token 刷新锁、业务 code 解析、平台路径拼接这些细节上保持各端行为一致。一旦漏掉其中一环,线上就可能出现「只有 iPhone 用户登录后白屏」「安卓用户总被反复登出」这类难以复现的问题。











