uni.addInterceptor('request') 是 uni-app 唯一全局请求拦截入口,仅拦截 uni.request,需在 main.js/app.js 早期注册;invoke 阶段用于参数标准化和鉴权注入,success/fail/complete 仅作通知不可改响应或中断请求。

uni.addInterceptor('request') 是唯一可行的全局请求拦截入口
uni-app 没有内置类似 Axios 的 request 拦截器,uni.addInterceptor('request') 是官方提供的、跨端可用的原生拦截机制。它不是“可选方案”,而是当前唯一能覆盖所有 uni.request 调用的全局钩子——无论你是直接调用 uni.request,还是封装在 service 层、API 文件里,只要最终走的是 uni-app 的请求通道,这个拦截器就生效。
注意:它只对 uni.request 生效,不拦截 uni.uploadFile、uni.downloadFile 等其他网络 API,这些需单独加拦截器。
常见错误现象:
• 写了 uni.addInterceptor('request', {...}) 却没看到日志输出 → 检查是否在 main.js 或 app.js 最早执行位置注册(不能晚于第一个请求发出);
• H5 正常、小程序无反应 → 小程序端必须确保基础库版本 ≥ 2.0.0(2026 年主流版本均已满足);
• success 钩子里修改 res.data 无效 → 响应数据不可变,只能读取或抛错,不能篡改返回值。
invoke 阶段必须做参数标准化和鉴权注入
invoke 是唯一能同步修改请求参数的时机,适合挂载 token、统一添加签名、补全 baseURL、过滤敏感字段等。这里出错,后续流程就全偏了。
实操建议:
- 不要直接拼接
args.url,先 normalize:用new URL(args.url, 'https://dummy.com').href或手动补前缀,避免相对路径导致 header 丢失 - token 必须严格校验:仅检查
uni.getStorageSync('token')是否存在远远不够,要判断typeof token === 'string' && token.trim().length > 0 - 后端要求 Bearer Token?写成
args.header.Authorization = `Bearer ${token}`,别漏空格 - 需要动态签名?把时间戳、随机数、sign 计算逻辑放在这里,别拖到 success 阶段
- 如果 args.data 是 FormData(如含文件上传),
args.header里不要设Content-Type,让小程序自动设置,否则会失败
success / fail / complete 钩子不能替代业务逻辑处理
这三个钩子是“事后通知”,不是“中间件”。它们无法中断或重发请求,也不能改变响应数据结构。很多开发者误以为在 success 里 res.data = transform(res.data) 能影响上层调用结果——实际完全无效,上层拿到的仍是原始响应。
典型误用场景:
- 在
success里跳转登录页 → 用户已看到空白页或报错再跳,体验割裂;正确做法是在invoke阶段预判权限(比如检查路由白名单 + token 存在性),或在业务层统一 catch 401 - 在
fail里重试请求 →fail只捕获网络层失败(如超时、断网),不包括 401/500 等 HTTP 状态码;重试逻辑必须自己封装 Promise + setTimeout,不能靠拦截器自动触发 - 在
complete里 hideLoading → 可以,但要注意:如果页面已销毁(如跳转离开),uni.hideLoading()会报错,建议加if (getCurrentPages().length > 0)守卫
小程序端特别注意平台能力鸿沟
微信小程序底层不支持 AbortController、Fetch Stream、自定义 timeout 字段,uni.addInterceptor 的 invoke 钩子也无法注入超时控制逻辑。这意味着:
• args.timeout 在小程序端被忽略,真正生效的是 uni.request 自身的 timeout 参数(需在业务调用时显式传入);
• 无法在拦截器里取消进行中的请求;
• fail 钩子捕获不到 401 这类状态码错误,只能靠 success 里手动判断 res.statusCode;
• 如果你依赖 responseType: 'arraybuffer',小程序端必须用 uni.downloadFile 替代,request 拦截器对此无效。
所以,真正的“全局参数拦截”只管得了一半:参数注入靠 invoke,状态处理和错误分类必须下沉到业务层或自定义 request 函数中,两者缺一不可。


















