在uni-app中,通过封装统一的网络请求工具并配置拦截器,可实现请求拦截、响应处理、错误提示和自动重试等功能。具体包括:1. 使用拦截器统一添加header、显示loading、处理状态码;2. 分类处理网络层、http、业务层错误,如断网提示、状态码日志记录、Token失效跳转登录;3. 封装全局错误监听与自动重试机制,提升应用健壮性;4. 引入配置项实现拦截器灵活控制,便于调试与线上行为分离,从而规范项目网络请求逻辑,提高可维护性。
在uni-app中,网络请求的拦截和错误处理是提升应用健壮性和用户体验的关键环节。很多人在开发过程中容易忽略这部分配置,导致接口异常时无法及时反馈或统一处理。其实通过合理使用拦截器和全局错误处理逻辑,可以有效减少重复代码、统一错误提示,还能自动做一些兜底操作,比如断网重试、token失效跳转登录等。
一、拦截器的作用与基本配置
拦截器本质上是对发起请求和响应返回这两个阶段进行“干预”。在uni-app中,通常基于uni.request封装一个统一的网络请求工具,并在其基础上添加请求拦截和响应拦截。
以常见的封装方式为例:
const http = { request(options) { // 请求拦截器 uni.showLoading({ title: '加载中' }); // 添加默认参数 options.url = 'https://api.example.com' + options.url; options.header = { ...options.header, 'Authorization': 'Bearer ' + store.getters.token }; return new Promise((resolve, reject) => { uni.request({ ...options, success: (res) => { // 响应拦截器 uni.hideLoading(); if (res.statusCode === 200) { resolve(res.data); } else { uni.showToast({ title: '请求异常', icon: 'none' }); reject(res); } }, fail: (err) => { uni.hideLoading(); uni.showToast({ title: '网络出错', icon: 'none' }); reject(err); } }); }); } };
在这个结构里,你可以在每次请求发出前统一加header、显示loading,在收到响应后判断状态码、隐藏loading、弹提示等。
二、常见错误类型及处理策略
网络请求可能遇到的错误大致分为三类:网络层错误(如无网、超时)、HTTP 错误(如404、500)、业务层错误(如 token 失效、权限不足)。
针对这几种情况,我们可以做不同的处理:
- 网络错误:弹窗提示用户检查网络连接,或者尝试重新发送一次。
- HTTP 状态码非 200:记录日志,展示通用错误信息。
- 业务错误:根据后端返回的特定字段(如 code !== 0)来提示具体问题,甚至触发特定行为(如跳回登录页)。
举个例子:
if (res.code === 401) { uni.showToast({ title: '身份已过期,请重新登录', icon: 'none' }); setTimeout(() => { uni.reLaunch({ url: '/pages/login/login' }); }, 1500); }
这类处理放在拦截器中会更集中,也更容易维护。
三、如何实现全局错误监听与自动重试
uni-app本身没有提供全局错误监听机制,但可以通过封装的方式来实现类似功能。例如,在封装的http.JS中统一处理错误,并对外暴露一个可配置的错误回调函数。
此外,还可以加上简单的重试机制,比如在失败时自动重试一次:
let retryCount = 0; function requestWithRetry(options) { return new Promise((resolve, reject) => { const doRequest = () => { http.request(options) .then(resolve) .catch((err) => { if (retryCount < 1) { retryCount++; uni.showToast({ title: '正在重试...', icon: 'loading' }); setTimeout(doRequest, 1000); } else { reject(err); } }); }; doRequest(); }); }
这种做法适用于一些偶发性错误,比如短暂断网、服务器不稳定等情况。
四、小技巧:把拦截器做得更灵活一点
如果你希望拦截器能根据不同环境(开发/生产)或不同模块做差异化处理,可以在封装的时候预留钩子函数,或者引入配置项。
比如:
const config = { enableLog: process.env.NODE_ENV === 'development', timeout: 10000 }; // 在拦截器中使用 config.enableLog 打印调试信息
这样既能方便调试,又不会影响线上行为。
基本上就这些了。拦截器不是什么高深技术,但用好了可以让整个项目的网络请求变得更规范、易维护。关键是把它封装好之后坚持使用,而不是到处写裸的uni.request。