还记得刚学Vue的时候,每次发请求都要写一堆重复代码的日子吗?
// 曾经的你,是否这样写过?
this.loading = true
axios.get('/api/data')
.then(response => {
this.data = response.data
this.loading = false
})
.catch(error => {
this.loading = false
alert('出错啦!')
console.log(error)
})
每个请求都要手动开关loading,每个错误都要单独处理... 累不累啊兄弟!
别担心,今天我要给你介绍的axios拦截器,就是来解救你于水火的!它就像给你的请求加了个“智能管家”,所有重复劳动统统自动化。
什么是拦截器?先来个通俗版解释
想象一下,你是个大老板,每天要收發很多快递(请求和响应)。拦截器就是你雇的两个贴心秘书:
- 请求秘书:每次你寄快递前,她自动帮你包装好、贴上标签、记下快递单号
- 响应秘书:每次收到快递,她先帮你拆箱检查,有问题直接处理,只把好东西交给你
这样一来,你只需要关心“要寄什么”和“收到后怎么用”,中间那些杂活秘书全包了!
实战开始:搭建你的拦截器帝国
第一步:基础装备
先确保你的项目里有axios:
npm install axios
然后创建一个专门的请求配置文件request.js:
// src/utils/request.js
import axios from 'axios'
// 创建axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 基础地址
timeout: 10000 // 超时时间
})
// 这里就是我们今天的主角——拦截器!
第二步:请求拦截器 - 你的贴心小秘书
请求拦截器会在请求发出前执行,适合做这些事:
- 自动添加token
- 统一加loading
- 参数序列化
// 请求拦截器
service.interceptors.request.use(
config => {
// 在发送请求前做些什么
// 1. 自动添加token
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
// 2. 显示loading(如果需要)
if (config.showLoading !== false) {
showLoading() // 你的loading显示方法
}
// 3. 记录请求开始时间(用于计算请求耗时)
config.startTime = Date.now()
console.log(`🚀 请求发出:${config.method?.toUpperCase()} ${config.url}`)
return config
},
error => {
// 对请求错误做些什么
hideLoading() // 记得隐藏loading
return Promise.reject(error)
}
)
看到没?以后发请求自动带token,再也不用每个请求手动设置了!
第三步:响应拦截器 - 你的质检专员
响应拦截器会在收到响应后执行,适合:
- 统一错误处理
- 自动隐藏loading
- 数据格式化
// 响应拦截器
service.interceptors.response.use(
response => {
// 2xx 范围内的状态码都会触发该函数
// 1. 隐藏loading
hideLoading()
// 2. 计算请求耗时
const costTime = Date.now() - response.config.startTime
console.log(`✅ 请求成功:${response.config.url} (${costTime}ms)`)
// 3. 直接返回数据部分,简化使用
return response.data
},
error => {
// 超出 2xx 范围的状态码都会触发该函数
// 1. 隐藏loading
hideLoading()
// 2. 计算请求耗时
const costTime = Date.now() - (error.config?.startTime || Date.now())
console.log(`❌ 请求失败:${error.config?.url} (${costTime}ms)`)
// 3. 统一错误处理
handleError(error)
return Promise.reject(error)
}
)
// 统一错误处理函数
function handleError(error) {
if (error.response) {
// 服务器返回错误状态码
const status = error.response.status
const message = error.response.data?.message || '请求错误'
switch (status) {
case 401:
// token过期,跳转到登录页
alert('登录已过期,请重新登录')
router.push('/login')
break
case 403:
alert('没有权限访问')
break
case 404:
alert('请求地址不存在')
break
case 500:
alert('服务器开小差了,请稍后重试')
break
default:
alert(message)
}
} else if (error.request) {
// 请求发出去但没有收到响应
alert('网络连接失败,请检查网络')
} else {
// 其他错误
alert(error.message)
}
}
第四步:完整实战代码 - 登录流程为例
来看一个完整的登录示例:
// src/utils/request.js
import axios from 'axios'
import { Toast } from 'vant' // 假设使用vant的提示组件
const service = axios.create({
baseURL: 'https://api.your-app.com',
timeout: 10000
})
let loadingCount = 0
function showLoading() {
if (loadingCount === 0) {
Toast.loading({
message: '加载中...',
forbidClick: true,
duration: 0
})
}
loadingCount++
}
function hideLoading() {
loadingCount--
if (loadingCount === 0) {
Toast.clear()
}
}
// 请求拦截器
service.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
if (config.showLoading !== false) {
showLoading()
}
config.startTime = Date.now()
return config
},
error => {
if (error.config?.showLoading !== false) {
hideLoading()
}
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
response => {
if (response.config.showLoading !== false) {
hideLoading()
}
const costTime = Date.now() - response.config.startTime
console.log(`请求成功:${response.config.url} (${costTime}ms)`)
// 根据你的后端返回结构调整
const res = response.data
if (res.code === 0 || res.success) {
return res
} else {
// 业务逻辑错误
Toast.fail(res.message || '请求失败')
return Promise.reject(new Error(res.message || 'Error'))
}
},
error => {
if (error.config?.showLoading !== false) {
hideLoading()
}
handleError(error)
return Promise.reject(error)
}
)
function handleError(error) {
if (error.response) {
const status = error.response.status
const message = error.response.data?.message || '请求错误'
switch (status) {
case 401:
Toast.fail('登录已过期')
setTimeout(() => {
localStorage.removeItem('token')
window.location.href = '/login'
}, 1500)
break
case 403:
Toast.fail('没有权限')
break
default:
Toast.fail(message)
}
} else if (error.request) {
Toast.fail('网络连接失败')
} else {
Toast.fail(error.message)
}
}
export default service
现在在组件中使用,简直爽到飞起:
// 在Vue组件中
import request from '@/utils/request'
export default {
methods: {
async login() {
try {
// 这么简洁!拦截器在背后默默处理了一切
const result = await request.post('/user/login', {
username: 'admin',
password: '123456'
})
// 直接拿到业务数据
if (result.success) {
this.$router.push('/dashboard')
}
} catch (error) {
// 错误已经被拦截器统一处理了,这里基本不用写东西
console.log('登录失败:', error)
}
},
async getData() {
// 某个不需要loading的请求
const data = await request.get('/api/data', {
showLoading: false // 个性化配置
})
this.data = data
}
}
}
高级玩法:让拦截器更智能
1. 请求重试机制
// 在响应拦截器中添加重试逻辑
service.interceptors.response.use(
response => response,
async error => {
const config = error.config
// 设置重试次数
if (!config.retryCount) {
config.retryCount = 3
}
if (config.retryCount > 0 &&
(error.response?.status >= 500 || !error.response)) {
config.retryCount--
// 延迟重试
await new Promise(resolve =>
setTimeout(resolve, 1000 * (3 - config.retryCount))
)
return service(config)
}
return Promise.reject(error)
}
)
2. 请求取消
在文件上传等场景特别有用:
// 创建取消令牌的Map
const pendingMap = new Map()
// 生成请求key
const getPendingKey = (config) => {
return [config.method, config.url].join('&')
}
// 请求拦截器中记录
service.interceptors.request.use(config => {
const key = getPendingKey(config)
removePending(key) // 取消重复请求
config.cancelToken = new axios.CancelToken(cancel => {
pendingMap.set(key, cancel)
})
return config
})
// 响应拦截器中移除
service.interceptors.response.use(response => {
const key = getPendingKey(response.config)
removePending(key)
return response
})
function removePending(key) {
if (pendingMap.has(key)) {
const cancel = pendingMap.get(key)
cancel(key)
pendingMap.delete(key)
}
}
常见坑位提醒
- 拦截器执行顺序:后添加的拦截器先执行(类似栈)
- 异步问题:拦截器支持Promise,可以做异步操作
- 多个实例:不同axios实例有自己独立的拦截器
- 错误传递:一定要用
Promise.reject传递错误,否则上层catch不到
总结
axios拦截器就像给你的项目请了个不要工资的全能助理:
- ✅ 自动管理认证token
- ✅ 统一loading状态
- ✅ 全局错误处理
- ✅ 请求日志记录
- ✅ 性能监控
- ✅ 数据格式化
从此告别重复代码,让你的Vue项目代码质量提升一个Level!以后再也不用在每个请求里写那些烦人的loading和错误处理了。
记住,好的工具要用在刀刃上。拦截器虽好,但也要根据实际项目需求来配置,别为了用而用。
赶紧去给你的项目配上这个神器吧,保证你用过之后就再也回不去了!
1万+

被折叠的 条评论
为什么被折叠?



