uni-app全局请求拦截器 uni-app如何统一处理token和错误码

1次阅读

uni.addInterceptor 是 uni-app 的原生请求拦截 API,仅 H5 和微信 / 支付宝等小程序支持,App 端(尤其 iOS)不生效,需手动封装 uni.request;token 注入需 Promise 化处理时序问题;401 应加刷新锁防并发;须分网络层与业务层双校验错误;跨端错误需统一包装。

uni.addInterceptor 是什么,哪些端能用?

uni.addinterceptor 是 uni-app 提供的原生拦截注册 api,但它 ** 不是全端可用 **——仅 h5 和微信 / 支付宝等主流小程序支持;app 端(尤其是 ios)基本不生效,uni.request 调用完全绕过它。很多开发者在 app 上写了拦截器却没反应,就是栽在这儿。

实际使用时得按端判断:

  • H5 / 小程序:可放心用 uni.addInterceptor('request', {……}) 做前置 URL 拼接、header 注入
  • App 端:必须手动封装 uni.request,不能依赖拦截器 API
  • 所有端统一行为:建议「以手动封装为主,uni.addInterceptor 为辅」,避免逻辑分裂

token 自动注入为什么不能只靠同步读取?

因为 token 往往存在异步获取场景:比如登录后存进 uni.setStorageSync,但某些模块(如首页请求)可能在 store 初始化前就发请求,uni.getStorageSync('token') 拿到的是空值,导致 401 —— 这不是代码写错了,是时序问题。

更稳妥的做法是:

  • 封装层加一层 Promise 化 token 获取逻辑(例如从 Pinia store 异步读,或 fallback 到 storage 同步读)
  • 对敏感接口(如用户中心)做 token 存在校验,缺失时主动 reject 并跳登录页,而不是静默发一个无 token 请求
  • 避免在拦截器里直接 uni.redirectTo,应把控制权交还业务层,否则测试和 mock 极难

401 错误处理最容易漏掉的并发刷新问题

当多个请求几乎同时收到 401,如果每个都触发 token 刷新流程,就会发多次刷新请求,后端可能拒绝或返回混乱状态。这不是理论风险,是真实线上高频问题。

正确做法是加一层「刷新锁」:

  • 用一个 refreshingPromise 变量缓存正在执行的刷新请求 Promise
  • 后续 401 请求先 await 它,复用结果,而不是各自重试
  • 刷新失败要清空该 Promise,否则后续请求永远卡住

示例关键逻辑:

let refreshingPromise = null;<br>if (res.statusCode === 401) {<br>  if (!refreshingPromise) {<br>    refreshingPromise = refreshToken();<br>  }<br>  await refreshingPromise;<br>  refreshingPromise = null;<br>  // 重发原请求 <br>}

错误码统一处理别只看 statusCode

后端返回 200 不代表业务成功,常见结构是 {code: 1001, msg: 'token 已过期', data: null}。只判 statusCode === 200 就 resolve,等于把业务错误当成功处理了。

应该分两层判断:

  • 网络层:检查 res.errMsg(如 "request:fail timeout")、res.statusCode 是否在 200–299 范围
  • 业务层:再解析 res.data,根据约定字段(如 code !== 0success === false)走错误分支
  • 不同错误类型分流处理:401 跳登录,1001 提示并清理本地态,其他弹 msg 即可

真正麻烦的是跨端错误信息不一致:小程序 fail 回调里 err 是字符串,H5 是 Error 对象,App 端还可能带 platform 字段——统一包装成标准错误对象,比硬扛各端差异更可持续。

实际项目里最常被忽略的,是 token 刷新后的请求重放机制和 loading 状态的嵌套控制。前者一漏就白刷 token,后者一错就出现“关了 loading 又弹新 loading”的体验断层。

星耀云
版权声明:本站原创文章,由 星耀云 2026-03-20发表,共计1653字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources