axios 是一个基于 Promise 的 HTTP 客户端,广泛用于前端与后台接口的交互。在 TypeScript 中,通过类型定义和接口约束,可以显著提高代码的可读性和安全性。本文将详细介绍如何使用 axios 进行规范的接口请求,并以 TypeScript 为例,重点讲解 GET 和 POST 请求的传参方式以及处理后台返回结果的实现。
1. 封装 axios 实例
通过封装 axios 实例,可以统一配置请求的基础 URL、超时时间、请求头等。
示例代码
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
// 创建 axios 实例
const instance: AxiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_BASE_URL || 'https://api.example.com', // 基础URL
timeout: 10000, // 请求超时时间
headers: {
'Content-Type': 'application/json', // 默认请求头
},
});
export default instance;
2. 统一处理请求和响应
使用拦截器统一处理请求和响应,例如添加认证 token、处理错误等。
请求拦截器
instance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 在请求发送之前添加认证 token
const token = localStorage.getItem('token');
if (token) {
config.headers = config.headers || {};
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse) => {
// 对响应数据进行处理,假设服务器返回的数据结构是 { code, message, data }
if (response.data.code === 200) {
return response.data.data; // 只返回实际数据
} else {
// 如果 code 不是 200,抛出错误
return Promise.reject(new Error(response.data.message || 'Request failed'));
}
},
(error) => {
// 对响应错误进行处理
if (error.response) {
switch (error.response.status) {
case 401:
// 处理未授权
break;
case 404:
// 处理未找到
break;
default:
// 处理其他错误
}
}
return Promise.reject(error);
}
);
3. GET 请求的传参与结果处理
GET 请求通常用于获取数据,参数通过 params 传递。
示例代码
interface User {
id: number;
name: string;
age: number;
}
// 定义 GET 请求的返回类型
interface ApiResponse<T> {
code: number;
message: string;
data: T;
}
// 获取用户信息
async function fetchUser(id: number): Promise<User> {
try {
const response = await instance.get<ApiResponse<User>>('/user', {
params: { id }, // GET 请求的参数
});
return response.data.data; // 返回实际数据
} catch (error) {
console.error('Error fetching user:', error.message);
throw error;
}
}
// 调用示例
fetchUser(12345)
.then((user) => {
console.log('User data:', user);
})
.catch((error) => {
console.error('Failed to fetch user:', error);
});
4. POST 请求的传参与结果处理
POST 请求通常用于提交数据,参数通过 data 传递。
示例代码
interface CreateUserRequest {
name: string;
age: number;
}
// 创建用户
async function createUser(userData: CreateUserRequest): Promise<User> {
try {
const response = await instance.post<ApiResponse<User>>('/user', userData); // POST 请求的参数
return response.data.data; // 返回实际数据
} catch (error) {
console.error('Error creating user:', error.message);
throw error;
}
}
// 调用示例
createUser({ name: 'John Doe', age: 30 })
.then((user) => {
console.log('User created:', user);
})
.catch((error) => {
console.error('Failed to create user:', error);
});
5. 文件上传
对于文件上传等特殊 POST 请求,可以使用 FormData 传递数据。
示例代码
async function uploadFile(file: File): Promise<string> {
const formData = new FormData();
formData.append('file', file);
try {
const response = await instance.post<ApiResponse<{ fileUrl: string }>>('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data.data.fileUrl; // 返回文件地址
} catch (error) {
console.error('Error uploading file:', error.message);
throw error;
}
}
// 调用示例
const file = document.querySelector('input[type="file"]')?.files?.[0];
if (file) {
uploadFile(file)
.then((fileUrl) => {
console.log('File uploaded:', fileUrl);
})
.catch((error) => {
console.error('Failed to upload file:', error);
});
}
6. 错误处理
在 catch 块中处理错误,或者使用响应拦截器统一处理错误。
示例代码
instance.get('/user')
.then((data) => {
console.log(data);
})
.catch((error) => {
if (error.response) {
// 请求已发出,但服务器响应状态码不在 2xx 范围内
console.error('Server error:', error.response.data);
} else if (error.request) {
// 请求已发出,但没有收到响应
console.error('No response received:', error.request);
} else {
// 其他错误
console.error('Request setup error:', error.message);
}
});
7. 取消请求
在需要时取消请求,避免不必要的网络请求。
示例代码
import { CancelTokenSource } from 'axios';
let cancelTokenSource: CancelTokenSource;
async function fetchUserWithCancel(id: number): Promise<User> {
cancelTokenSource = axios.CancelToken.source();
try {
const response = await instance.get<ApiResponse<User>>('/user', {
params: { id },
cancelToken: cancelTokenSource.token,
});
return response.data.data;
} catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
console.error('Error fetching user:', error.message);
}
throw error;
}
}
// 取消请求
function cancelRequest() {
if (cancelTokenSource) {
cancelTokenSource.cancel('Operation canceled by the user.');
}
}
8. 环境变量
将 API 的基础 URL 等配置放在环境变量中,便于在不同环境中切换。
示例代码
const instance: AxiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
总结
在 TypeScript 中使用 axios 请求后台接口时,遵循以下规范和最佳实践:
- 封装
axios实例:统一配置请求的基础 URL、超时时间、请求头等。 - 拦截器:统一处理请求和响应,例如添加认证 token、处理错误等。
- GET 请求:使用
params传递参数,返回结果通过泛型定义类型。 - POST 请求:使用
data传递参数,返回结果通过泛型定义类型。 - 文件上传:使用
FormData传递文件数据。 - 错误处理:统一处理网络错误、服务器错误和业务逻辑错误。
- 取消请求:在需要时取消请求,避免不必要的网络请求。
通过以上规范,可以显著提高代码的可读性、可维护性和安全性。