如果还没看本专栏的上一篇文章,请移步。
本文章旨在提供分层封装axios后的实际使用api的方法。
API 请求使用指南
1. 基础使用
1.1 导入 HTTP 客户端
import { http } from '@/utils/request'
1.2 发送 GET 请求
// 基本 GET 请求
const getData = async () => {
try {
const data = await http.get('/api/endpoint')
console.log('获取数据成功:', data)
} catch (error) {
console.error('获取数据失败:', error)
}
}
// 带参数的 GET 请求
const getWithParams = async (id: string) => {
try {
const data = await http.get('/api/items', { id, page: 1, size: 10 })
console.log('获取列表数据:', data)
} catch (error) {
console.error('获取列表失败:', error)
}
}
1.3 发送 POST 请求
// 基本 POST 请求
const createItem = async (itemData: any) => {
try {
const result = await http.post('/api/items', itemData)
console.log('创建成功:', result)
return result
} catch (error) {
console.error('创建失败:', error)
throw error
}
}
2. 类型安全请求
2.1 定义响应类型
// types/user.ts
export interface User {
id: number
username: string
email: string
avatarUrl?: string
// 其他用户字段...
}
// 定义 API 响应类型
export interface ApiResponse<T> {
code: number
data: T
message: string
}
2.2 使用类型发送请求
import { http } from '@/utils/request'
import type { User, ApiResponse } from '@/types/user'
// 获取用户信息
const fetchUser = async (userId: number): Promise<User> => {
try {
const user = await http.get<User>(`/users/${userId}`)
return user
} catch (error) {
console.error('获取用户信息失败:', error)
throw error
}
}
// 创建用户
const createUser = async (userData: Omit<User, 'id'>): Promise<User> => {
try {
const newUser = await http.post<User>('/users', userData)
return newUser
} catch (error) {
console.error('创建用户失败:', error)
throw error
}
}
3. 文件上传
const uploadFile = async (file: File) => {
try {
const formData = new FormData()
formData.append('file', file)
const result = await http.upload('/upload', file)
console.log('上传成功:', result)
return result
} catch (error) {
console.error('上传失败:', error)
throw error
}
}
// 在组件中使用
const handleFileChange = (event: Event) => {
const input = event.target as HTMLInputElement
if (input.files && input.files[0]) {
uploadFile(input.files[0])
}
}
4. 错误处理
4.1 基本错误处理
const fetchData = async () => {
try {
const data = await http.get('/api/data')
return data
} catch (error) {
// 错误已经在 request.ts 中统一处理
// 这里可以添加额外的错误处理逻辑
console.error('自定义错误处理:', error)
throw error // 重新抛出错误,让调用方也能处理
}
}
4.2 自定义错误处理
import { handleApiError } from '@/api/apiError'
const fetchWithCustomErrorHandling = async () => {
try {
const data = await http.get('/api/data')
return data
} catch (error) {
// 自定义错误处理
if (error.response?.status === 404) {
console.error('资源未找到')
} else if (error.response?.status === 401) {
// 未授权,跳转到登录页
router.push('/login')
} else {
// 使用统一的错误处理
handleApiError(error)
}
throw error
}
}
5. 请求配置
5.1 自定义请求头
const fetchWithCustomHeaders = async () => {
try {
const data = await http.get('/api/data', {
headers: {
'X-Custom-Header': 'value',
'Authorization': 'Bearer custom-token'
}
})
return data
} catch (error) {
console.error('请求失败:', error)
throw error
}
}
5.2 取消请求
import axios from 'axios'
// 创建取消令牌
const CancelToken = axios.CancelToken
const source = CancelToken.source()
// 发送请求
const fetchData = async () => {
try {
const data = await http.get('/api/data', {
cancelToken: source.token
})
return data
} catch (error) {
if (axios.isCancel(error)) {
console.log('请求已被取消:', error.message)
} else {
console.error('请求失败:', error)
}
throw error
}
}
// 取消请求
const cancelRequest = () => {
source.cancel('用户取消了请求')
}
6. 响应拦截器使用
响应拦截器已经内置在 request.ts
中,会自动处理以下内容:
- 自动添加 token 到请求头
- 统一处理响应数据
- 处理 HTTP 错误状态码
- 处理业务错误码
- 未授权(401)自动跳转登录页
7. 最佳实践
7.1 创建 API 服务模块
// src/api/user.ts
import { http } from '@/utils/request'
import type { User } from '@/types/user'
export const userApi = {
// 获取用户信息
getProfile: async (): Promise<User> => {
return http.get('/user/profile')
},
// 更新用户信息
updateProfile: async (userData: Partial<User>): Promise<User> => {
return http.put('/user/profile', userData)
},
// 上传头像
uploadAvatar: async (file: File): Promise<{ avatarUrl: string }> => {
return http.upload('/user/avatar', file)
}
}
7.2 在 Vue 组件中使用
<template>
<div>
<div v-if="loading">加载中...</div>
<div v-else-if="error">{{ error }}</div>
<div v-else>
<h1>{{ user.username }}</h1>
<p>{{ user.email }}</p>
<input type="file" @change="handleAvatarChange" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { userApi } from '@/api/user'
import type { User } from '@/types/user'
const user = ref<Partial<User>>({})
const loading = ref(false)
const error = ref('')
// 获取用户信息
const fetchUserProfile = async () => {
try {
loading.value = true
error.value = ''
user.value = await userApi.getProfile()
} catch (err) {
error.value = err.message || '获取用户信息失败'
} finally {
loading.value = false
}
}
// 更新头像
const handleAvatarChange = async (event: Event) => {
const input = event.target as HTMLInputElement
if (input.files && input.files[0]) {
try {
loading.value = true
const result = await userApi.uploadAvatar(input.files[0])
user.value.avatarUrl = result.avatarUrl
} catch (err) {
error.value = err.message || '上传头像失败'
} finally {
loading.value = false
}
}
}
// 组件挂载时获取用户信息
onMounted(() => {
fetchUserProfile()
})
</script>
8. 常见问题
8.1 跨域问题
如果遇到跨域问题,请确保:
- 后端已配置 CORS 头
- withCredentials 配置正确
- 前端请求的域名和端口与后端允许的匹配
8.2 请求超时
默认请求超时时间为 10 秒,可以在 request.ts
中修改:
const request = axios.create({
// ...
timeout: 15000, // 修改为 15 秒
// ...
})
8.3 调试请求
可以在浏览器的开发者工具的 Network 标签页中查看所有请求和响应。
9. 总结
- 使用
http.get
,http.post
等方法发送请求 - 使用 TypeScript 接口确保类型安全
- 错误处理已经内置,也可以自定义处理
- 文件上传使用
http.upload
方法 - 遵循最佳实践组织 API 代码
通过本指南,您应该能够轻松地在前端应用中使用封装好的 HTTP 客户端进行数据交互。