uni.request封装需按端区分url拼接:h5用相对路径配合代理,小程序/app必须用完整https地址;token须同步读取、展开合并header;401错误应抛出而非跳转,由页面层统一处理。
直接挂载到 vue.prototype 或 app.config.globalproperties 是可行的,但必须处理好跨平台 url 拼接、token 注入、错误统一拦截这三件事,否则 h5 代理、小程序域名限制、app 端证书校验会接连报错。
uni.request 封装后如何正确拼接 baseURL?
不同端对 URL 的处理逻辑不一致:uni.request 在 H5 端支持相对路径(配合 webpack 代理),但在小程序和 APP-PLUS 端必须是完整 HTTPS 协议地址。硬拼 baseUrl + url 会导致小程序 404 或 H5 请求发向错误域名。
- 用
#ifdef H5/#ifndef H5条件编译区分:H5 用代理前缀(如/api),其他端用真实线上域名 - 避免在封装里写死
https://开头的baseUrl,而是通过配置文件 + 环境变量动态注入(如process.env.NODE_ENV) - URL 参数中若含查询字符串(
?),不要手动拼接,应交给uni.request自动处理;否则 H5 代理可能无法识别 - 示例判断逻辑:
const url = options.url.startsWith('http') ? options.url : (isH5 ? '/api' + options.url : config.baseUrl + options.url)
为什么 Token 总是没带上或被覆盖?
常见原因是 header 合并顺序出错:用户传入的 header 直接覆盖了默认 header,导致 Authorization 丢失;或者 token 读取时机不对(如异步登录未完成就发请求)。
- 必须用展开运算符合并 header:
{ 'Content-Type': 'application/json', ...options.header, 'Authorization': token } - token 应从
uni.getStorageSync('token')同步读取,不要依赖异步状态管理(如 Pinia store 中未 commit 就调用) - 响应中若返回新 token(如
res.header.authorization),需立即同步写入本地存储,否则下个请求仍用旧 token - 小程序端注意:
header键名大小写敏感,authorization无效,必须是Authorization
401 错误跳转登录页为何不生效?
根本原因在于 uni.redirectTo 在非页面上下文中不可用(比如在 utils/request.js 里调用),且 Promise 链中 throw error 后未被上层 catch 捕获,导致静默失败。
- 不要在 request 封装内部做页面跳转,只负责抛出标准化错误(如
{ code: 401, message: '登录过期' }) - 页面层统一用
try/catch或.catch()接收,并在onShow或业务入口处检查登录态 - 若用 Vue 3 + Composition API,可在
onMounted中调用请求并处理 401;避免在setup顶层执行异步请求 - APP-PLUS 端
uni.navigateTo需确保目标页面已注册,否则白屏无提示
最易被忽略的是「请求取消」和「重复提交」控制——没有防抖或 pending 队列时,列表下拉刷新+搜索框输入同时触发多个相同请求,不仅浪费资源,还可能导致界面状态错乱。这需要在封装层用 Map 缓存请求 key 并主动调用 uni.cancelRequest(仅 APP/H5 支持),小程序端只能靠业务层节流。











