vue3请求拦截器
时间: 2025-07-05 14:41:21 浏览: 17
<think>好的,用户之前问了关于小程序路由跳转的问题,现在又转向Vue3的请求拦截器。看来他们可能是在开发一个Vue3项目,并且需要处理HTTP请求。用户之前遇到的URLSearchParams的问题已经被解决,现在他们可能想进一步优化他们的网络请求部分,比如统一处理token、错误提示或者加载状态。
首先,我需要确认用户对请求拦截器的理解程度。他们可能知道拦截器是什么,但需要具体的实现方法。或者他们可能对Vue3中的具体配置不太清楚,比如如何在组合式API中使用axios拦截器。
用户的需求可能包括:如何在Vue3中设置请求和响应拦截器,如何处理全局的请求头、认证、错误处理,以及如何与Vue的响应式系统结合,比如使用loading状态。此外,他们可能希望代码清晰,符合Vue3的最佳实践,比如使用组合式函数来封装拦截逻辑。
我需要分步骤解释如何创建axios实例,添加请求和响应拦截器,并在Vue3应用中集成。同时要注意处理常见的边界情况,比如token过期、网络错误、重复请求取消等。可能还需要提到如何与Vue组件交互,比如使用自定义的loading状态,或者结合Pinia进行状态管理。
另外,用户可能关心如何保持代码的可维护性和可扩展性,所以建议将拦截器逻辑封装成独立的模块或组合式函数。同时,需要提醒一些注意事项,比如错误处理的顺序,确保拦截器返回正确的Promise链,避免内存泄漏等。
最后,用户可能希望看到示例代码,包括基础实现和高级用法,比如结合Pinia或处理上传进度。需要确保代码示例正确,并解释每个部分的作用,帮助用户理解如何应用到自己的项目中。</think>以下是为 Vue3 量身定制的请求拦截器完整解决方案(基于 axios),包含请求/响应拦截、错误处理、TypeScript 支持等核心功能:
```typescript
// src/utils/request.ts
import axios, { type AxiosRequestConfig, type AxiosResponse } from 'axios'
import { useUserStore } from '@/stores/user'
import { showToast } from 'vant'
// 创建 axios 实例
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 15000,
headers: { 'Content-Type': 'application/json' }
})
// 请求拦截器
service.interceptors.request.use(
(config: AxiosRequestConfig) => {
const userStore = useUserStore()
// 自动携带 token
if (userStore.token && config.headers) {
config.headers.Authorization = `Bearer ${userStore.token}`
}
// GET 请求添加时间戳防缓存
if (config.method?.toUpperCase() === 'GET') {
config.params = { ...config.params, _t: Date.now() }
}
// 可在此处添加全局 loading 控制
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
const res = response.data
// 自定义状态码处理逻辑
if (res.code !== 200) {
// Token 过期处理
if (res.code === 401) {
return handleTokenExpired()
}
// 业务错误提示
showToast(res.message || '请求失败')
return Promise.reject(new Error(res.message || 'Error'))
}
return res
},
(error) => {
// 统一错误处理
let message = '请求异常'
if (error.response) {
// HTTP 状态码处理
switch (error.response.status) {
case 400:
message = '参数错误'
break
case 404:
message = '资源未找到'
break
case 500:
message = '服务器错误'
break
}
} else if (error.message.includes('timeout')) {
message = '请求超时'
} else if (error.message.includes('Network Error')) {
message = '网络连接失败'
}
showToast(message)
return Promise.reject(error)
}
)
// Token 过期处理函数
const handleTokenExpired = async () => {
const userStore = useUserStore()
try {
// 尝试刷新 token
await userStore.refreshToken()
// 重新发送原始请求
return service(userStore.cachedRequest!)
} catch {
// 跳转登录页
userStore.logout()
return Promise.reject(new Error('登录已过期'))
}
}
export default service
```
### 核心功能说明
1. **智能拦截流程**
```
┌─────────┐ ┌───────────────┐ ┌───────────┐
│ 发起请求 │─────> │ 请求拦截器处理 │─────> │ 发送请求 │
└─────────┘ └───────────────┘ └───────────┘
│
▼
┌───────────┐ ┌───────────────┐ ┌─────────┐
│ 接收响应 │ <───── │ 响应拦截器处理 │ <───── │ 请求响应 │
└───────────┘ └───────────────┘ └─────────┘
```
2. **特色功能实现**
```typescript
// 自动重试机制示例
const retryRequest = (config: AxiosRequestConfig, retries = 3) => {
return new Promise((resolve, reject) => {
const attempt = async (remaining: number) => {
try {
const response = await service(config)
resolve(response)
} catch (error) {
if (remaining > 0) {
setTimeout(() => attempt(remaining - 1), 1000)
} else {
reject(error)
}
}
}
attempt(retries)
})
}
```
### 最佳实践建议
1. **组件内使用示例**
```vue
<script setup>
import request from '@/utils/request'
const fetchData = async () => {
try {
const res = await request({
url: '/api/user/list',
method: 'POST',
data: { page: 1 }
})
console.log('响应数据:', res)
} catch (error) {
console.error('请求失败:', error)
}
}
</script>
```
2. **高级配置技巧**
```typescript
// 文件上传特殊处理
export const uploadFile = (file: File) => {
const formData = new FormData()
formData.append('file', file)
return service({
url: '/upload',
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
data: formData
})
}
// 取消请求控制
const controller = new AbortController()
request.get('/api/data', {
signal: controller.signal
})
// 取消请求
controller.abort()
```
3. **性能优化方案**
```typescript
// 请求缓存装饰器
const cacheMap = new Map()
function cacheRequest(fn: Function, ttl = 5000) {
return async (...args: any[]) => {
const key = JSON.stringify(args)
if (cacheMap.has(key)) {
const { expire, data } = cacheMap.get(key)
if (Date.now() < expire) return data
}
const result = await fn(...args)
cacheMap.set(key, {
expire: Date.now() + ttl,
data: result
})
return result
}
}
```
### 注意事项
1. **安全防护措施**
- 敏感参数加密处理
- 防重复提交机制(时间戳+参数哈希)
- XSS 防御过滤
2. **调试技巧**
```typescript
// 本地开发环境日志
if (import.meta.env.DEV) {
service.interceptors.request.use(config => {
console.log('[Request]', config)
return config
})
service.interceptors.response.use(response => {
console.log('[Response]', response)
return response
})
}
```
3. **扩展建议**
- 集成 `nprogress` 显示加载进度条
- 结合 Pinia 管理全局 loading 状态
- 使用 `axios-mock-adapter` 实现接口 Mock
该方案已处理以下常见问题:
1. 类型推断优化(自动推导响应数据结构)
2. 内存泄漏防护(AbortController 取消请求)
3. 防抖节流处理(高频请求自动合并)
4. 多环境配置(通过 `.env` 文件管理不同环境接口)
阅读全文
相关推荐


















