uni.request不能直接加拦截器,必须手动封装一层函数来实现请求前预处理(如baseURL拼接、token注入)和响应后分类处理(网络异常、HTTP错误、业务错误),所有请求须显式调用该封装函数。

uni.request 不能直接加拦截器,必须封装一层
直接在 uni.request 上挂 .interceptors 或调用 uni.addInterceptor('request') 是无效的——前者属性根本不存在,后者只对部分平台(如 H5)有作用,小程序端完全不生效。官方从未提供请求级的全局拦截 API,所有“拦截”都得靠你自己写个函数包住 uni.request。
常见错误现象:uni.request.interceptors is undefined、uni.addInterceptor('request') 在微信小程序里静默失效、H5 正常但小程序 token 没发出去。
- 所有网络请求必须显式 import 你封装的
request函数,不能继续直调uni.request - 封装函数要返回 Promise,否则 await 不住
- 不要试图 patch
uni.request原函数——各端底层实现不同,劫持后 H5 可能正常,小程序直接报错或无响应 - 环境变量(如
UNI_PLATFORM)要在封装层读取,不能只靠process.env.NODE_ENV判断 baseURL
封装 request 时如何注入和修改全局参数
核心是控制请求发出前的 options 对象:拼接 baseURL、注入 token、统一 header、处理 GET 参数序列化等。关键不是“拦截”,而是“预处理”。
示例中容易踩的坑:header 合并写成 { ...options.header, Authorization: token } 会丢失默认值;GET 请求没把 data 转成 query string 就直接发出去,后端收不到参数。
-
url拼接优先用new URL(options.url, baseURL),比字符串拼接更安全(自动处理斜杠、协议等) - token 从
uni.getStorageSync('token')读取,但注意小程序冷启动时 storage 可能为空,需 fallback 处理 - GET 请求的
data必须手动转 query:用Object.keys(data).map(k => `${k}=${encodeURIComponent(data[k])}`).join('&') - 如果项目用了 TypeScript,给封装函数加上完整类型定义,避免
options.success和options.fail类型冲突
为什么 uni.addInterceptor('request') 在小程序里基本没用
它不是设计来拦截 uni.request 的。文档里没明说,但实际行为是:仅在 H5 平台触发 invoke/success/fail,微信/支付宝小程序端注册后完全不回调。这不是 bug,是平台能力限制——小程序原生 wx.request 不暴露中间生命周期,uni-app 无法桥接。
有人试过在 main.js 里注册,发现部分接口漏拦截,原因就是:这个 API 实际只覆盖了 uni-app 自己封装的少数内部调用路径(比如某些内置组件的请求),而非所有 uni.request 调用。
- 别把它和 axios 的拦截器类比,二者机制完全不同
- 如果你看到某篇教程说“一行代码启用请求拦截”,大概率是只测了 H5,没跑小程序真机
- 真正跨端稳定的方案只有:封装 + 全项目替换调用点
修改参数后如何保证 error 分类不混乱
封装后的 request 必须明确区分三类失败:网络异常(fail 回调)、HTTP 状态码异常(success 里 statusCode !== 200)、业务错误码(如 res.data.code === 401)。混在一起处理会导致 loading 关不掉、错误 toast 叠加、登录跳转重复触发。
典型问题:401 响应进了 success 回调,但没检查 res.statusCode 就直接 resolve,导致业务层拿到一个“成功响应”却包含错误数据。
- network error(断网、超时)走
fail回调,此时res是 undefined,不要试图解构 - HTTP error(如 404、500)走
success,但res.statusCode不在 200–299 范围,应 reject 并附带原始 res - 业务 error(如
{ code: 401, msg: '登录过期' })在 success 且 statusCode 正常的前提下二次判断,单独 throw 或 dispatch 登录事件 - 所有 reject 都要确保调用
uni.hideLoading(),否则 loading 会一直卡住
uni.request 调用,并确保每个页面、每个组件、每个 store action 都用的是新函数——漏一处,就有一处请求逃逸全局逻辑。


















