悠悠楠杉
uni-app网络请求拦截器配置与全局错误处理实战指南
一、为什么需要拦截器?
在uni-app开发中,我们经常需要处理以下场景:
- 所有请求需要自动携带Authorization头
- 401状态码时自动跳转登录页
- 服务器响应格式标准化处理
- 网络异常时的统一提示
通过拦截器可以避免在每个请求中重复编写相同逻辑,实现"一次配置,全局生效"的效果。
二、基础拦截器配置
uni-app基于axios的拦截器机制,以下是基础配置示例:
javascript
// utils/http.js
const http = uni.$u.http
// 请求拦截
http.interceptors.request.use(
config => {
// 注入token
const token = uni.getStorageSync('token')
if (token) {
config.header['Authorization'] = Bearer ${token}
}
// 处理Content-Type
if (!config.header['Content-Type']) {
config.header['Content-Type'] = 'application/json'
}
return config
},
error => {
return Promise.reject(error)
}
)
// 响应拦截
http.interceptors.response.use(
response => {
// 处理二进制数据
if (response.config.responseType === 'blob') {
return response.data
}
// 按业务逻辑处理响应数据
if (response.data.code !== 200) {
return Promise.reject(response.data)
}
return response.data.data
},
error => {
// 错误处理留到后续章节详解
return Promise.reject(error)
}
)
三、进阶错误处理方案
3.1 错误分类处理
javascript
const errorHandler = (error) => {
const { statusCode, errMsg } = error
// 网络层错误
if (!statusCode) {
uni.showToast({
title: '网络连接异常',
icon: 'none'
})
return
}
// HTTP状态码处理
switch(statusCode) {
case 401:
handleAuthError()
break
case 500:
uni.showToast({ title: '服务器开小差了', icon: 'none' })
break
default:
console.error('未处理的HTTP状态:', statusCode)
}
// 业务错误码处理
if (error.code) {
businessErrorHandler(error)
}
}
3.2 Token自动刷新机制
javascript
let isRefreshing = false
let requests = []
const refreshToken = () => {
return new Promise((resolve) => {
uni.login({
success: async (res) => {
const newToken = await api.refreshToken(res.code)
uni.setStorageSync('token', newToken)
resolve()
}
})
})
}
http.interceptors.response.use(null, async (error) => {
if (error.statusCode === 401 && !error.config._retry) {
if (!isRefreshing) {
isRefreshing = true
await refreshToken()
isRefreshing = false
requests.forEach(cb => cb())
requests = []
}
return new Promise(resolve => {
requests.push(() => {
resolve(http(error.config))
})
})
}
return Promise.reject(error)
})
四、性能优化技巧
- 请求取消:使用AbortController实现长请求取消javascript
const controller = new AbortController()
http.get('/api', {
signal: controller.signal
})
// 需要取消时
controller.abort()
缓存策略:对GET请求添加本地缓存javascript
const cacheRequest = (url) => {
const cache = uni.getStorageSync(url)
if (cache && Date.now() - cache.time < 600000) {
return Promise.resolve(cache.data)
}return http.get(url).then(res => {
uni.setStorageSync(url, { data: res, time: Date.now() })
return res
})
}请求合并:使用lodash的debounce合并高频请求
五、调试与监控
- 日志记录:javascript
http.interceptors.request.use(config => {
console.log([Request] ${config.method} ${config.url}
, config.data)
return config
})
http.interceptors.response.use(response => {
console.log([Response] ${response.statusCode}
, response.data)
return response
})
- 性能监控:javascript
config.metadata = { startTime: Date.now() }
http.interceptors.response.use(response => {
const duration = Date.now() - response.config.metadata.startTime
console.log(请求耗时: ${duration}ms
)
return response
})
总结:完善的拦截器系统应当包含请求预处理、响应标准化、错误分级处理、安全控制等模块。实际项目中建议根据业务需求扩展重试机制、请求队列、离线缓存等高级功能,并通过TypeScript强化类型检查,构建企业级网络请求架构。