Axios是一个基于Promise的HTTP客户端,可以在浏览器和Node.js环境中使用。它具有强大的功能和简洁的API,已成为前端开发中处理网络请求的首选工具。
1. Axios 基本介绍
Axios的主要特点:
- 基于Promise:支持Promise API,可以使用async/await语法
- 跨平台:同时支持浏览器和Node.js环境
- 拦截请求和响应:可以在请求发送前或响应返回后进行处理
- 转换请求和响应数据:自动转换JSON数据
- 取消请求:支持取消请求功能
- 自动处理CSRF保护:客户端支持防御XSRF攻击
- 支持上传下载进度监控:可以监控上传和下载的进度
2. 安装与使用
安装
# 使用npm安装
npm install axios
# 使用yarn安装
yarn add axios
# 使用pnpm安装
pnpm add axios
基本使用
// 导入axios
import axios from 'axios';
// 发起GET请求
axios.get('/user?ID=12345')
.then(function (response) {
// 处理成功情况
console.log(response.data);
})
.catch(function (error) {
// 处理错误情况
console.log(error);
})
.finally(function () {
// 总是会执行
});
// 使用async/await
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response.data);
} catch (error) {
console.error(error);
}
}
3. 请求方法
Axios支持所有常见的HTTP请求方法:
// GET请求
axios.get(url[, config])
// POST请求
axios.post(url[, data[, config]])
// PUT请求
axios.put(url[, data[, config]])
// DELETE请求
axios.delete(url[, config])
// HEAD请求
axios.head(url[, config])
// OPTIONS请求
axios.options(url[, config])
// PATCH请求
axios.patch(url[, data[, config]])
4. 请求配置
Axios请求可以通过配置对象进行自定义:
axios({
method: 'post', // 请求方法
url: '/user/12345', // 请求URL
data: { // 请求体数据
firstName: '张',
lastName: '三'
},
headers: { // 自定义请求头
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
},
params: { // URL参数
ID: 12345
},
timeout: 1000, // 请求超时时间(毫秒)
responseType: 'json', // 响应类型
withCredentials: false // 是否携带凭证
})
5. 创建实例
可以创建自定义的Axios实例,便于设置基本配置:
// 创建自定义实例
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {'X-Custom-Header': 'foobar'}
});
// 使用实例发送请求
instance.get('/user')
.then(response => console.log(response.data));
6. 拦截器
Axios的拦截器是其最强大的功能之一,允许在请求发送前和响应接收后进行处理。
请求拦截器
// 添加请求拦截器
axios.interceptors.request.use(
config => {
// 在发送请求之前做些什么
// 例如:添加认证信息
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
响应拦截器
// 添加响应拦截器
axios.interceptors.response.use(
response => {
// 对响应数据做点什么
return response;
},
error => {
// 对响应错误做点什么
if (error.response) {
// 服务器返回了错误状态码
if (error.response.status === 401) {
// 未授权,可能需要重新登录
console.log('未授权,请重新登录');
} else if (error.response.status === 404) {
console.log('请求的资源不存在');
} else if (error.response.status >= 500) {
console.log('服务器错误,请稍后再试');
}
} else if (error.request) {
// 请求已发出,但没有收到响应
console.log('网络错误,请检查您的网络连接');
} else {
// 请求配置出错
console.log('请求配置错误:', error.message);
}
return Promise.reject(error);
}
);
7. 错误处理最佳实践
错误处理是使用Axios时的重要部分,以下是一些最佳实践:
// 创建一个axios实例
const api = axios.create({
baseURL: '/api',
timeout: 10000
});
// 统一错误处理
api.interceptors.response.use(
response => {
// 如果后端约定返回格式包含success字段
const res = response.data;
if (res.success === false) {
// 业务逻辑错误
console.error(res.message || '操作失败');
// 可以使用UI库显示错误信息
// Message.error(res.message || '操作失败');
return Promise.reject(new Error(res.message || '操作失败'));
}
return res; // 直接返回数据部分,简化后续使用
},
error => {
let message = '';
if (error.response) {
// HTTP状态码相关错误
switch (error.response.status) {
case 400:
message = '请求错误';
break;
case 401:
message = '未授权,请重新登录';
// 可以在这里处理登出逻辑
break;
case 403:
message = '拒绝访问';
break;
case 404:
message = '请求地址出错';
break;
case 408:
message = '请求超时';
break;
case 500:
message = '服务器内部错误';
break;
case 501:
message = '服务未实现';
break;
case 502:
message = '网关错误';
break;
case 503:
message = '服务不可用';
break;
case 504:
message = '网关超时';
break;
default:
message = `未知错误 ${error.response.status}`;
}
} else if (error.request) {
message = '网络异常,请检查您的网络连接';
} else {
message = error.message;
}
console.error(message);
// 可以使用UI库显示错误信息
// Message.error(message);
return Promise.reject(error);
}
);
8. 取消请求
Axios支持取消请求,有两种方式:
使用AbortController(推荐,v0.22.0+)
// 创建一个AbortController实例
const controller = new AbortController();
// 发送请求
axios.get('/api/data', {
signal: controller.signal
}).catch(function(error) {
if (axios.isCancel(error)) {
console.log('请求已被取消', error.message);
} else {
// 处理错误
}
});
// 取消请求
controller.abort();
使用CancelToken(已弃用)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/api/data', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('请求已被取消', thrown.message);
} else {
// 处理错误
}
});
// 取消请求
source.cancel('操作被用户取消');
9. 处理表单数据
x-www-form-urlencoded格式
// 使用URLSearchParams
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/api/form', params);
// 使用qs库
import qs from 'qs';
axios.post('/api/form', qs.stringify({ param1: 'value1', param2: 'value2' }));
// axios自动序列化(v0.27.0+)
axios.post('/api/form', { param1: 'value1', param2: 'value2' }, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
multipart/form-data格式(文件上传)
// 使用FormData
const formData = new FormData();
formData.append('file', document.querySelector('#fileInput').files[0]);
formData.append('name', 'file名称');
axios.post('/api/upload', formData);
// axios自动序列化(v0.27.0+)
axios.post('/api/upload', {
file: document.querySelector('#fileInput').files[0],
name: 'file名称'
}, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
10. 进度监控
Axios支持上传和下载进度监控:
axios.post('/api/upload', formData, {
onUploadProgress: function(progressEvent) {
// 处理上传进度
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`上传进度: ${percentCompleted}%`);
},
onDownloadProgress: function(progressEvent) {
// 处理下载进度
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`下载进度: ${percentCompleted}%`);
}
});
11. 实际项目中的封装示例
在实际项目中,通常会对Axios进行封装,以下是一个完整的封装示例:
import axios from 'axios';
import { Message } from 'element-ui'; // 假设使用Element UI
import router from '@/router'; // 假设使用Vue Router
// 创建axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 从环境变量中获取API基础URL
timeout: 10000 // 请求超时时间
});
// 请求拦截器
service.interceptors.request.use(
config => {
// 从localStorage获取token
const token = localStorage.getItem('token');
if (token) {
// 设置token到请求头
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
error => {
console.log(error);
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data;
// 如果后端约定返回格式包含code字段
if (res.code !== 200) {
Message({
message: res.message || '操作失败',
type: 'error',
duration: 5 * 1000
});
// 处理特定的错误码
if (res.code === 401) {
// 未授权,可能是token过期
// 弹出确认框,询问是否重新登录
MessageBox.confirm(
'您的登录已过期,请重新登录',
'确认退出',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
// 清除用户信息并跳转到登录页
localStorage.removeItem('token');
router.push(`/login?redirect=${router.currentRoute.fullPath}`);
});
}
return Promise.reject(new Error(res.message || '操作失败'));
} else {
// 直接返回数据部分,简化后续使用
return res.data;
}
},
error => {
let message = '';
if (error.response) {
// HTTP状态码相关错误
switch (error.response.status) {
case 400:
message = '请求错误';
break;
case 401:
message = '未授权,请重新登录';
// 清除用户信息并跳转到登录页
localStorage.removeItem('token');
router.push(`/login?redirect=${router.currentRoute.fullPath}`);
break;
case 403:
message = '拒绝访问';
break;
case 404:
message = '请求地址出错';
break;
case 408:
message = '请求超时';
break;
case 500:
message = '服务器内部错误';
break;
case 501:
message = '服务未实现';
break;
case 502:
message = '网关错误';
break;
case 503:
message = '服务不可用';
break;
case 504:
message = '网关超时';
break;
default:
message = `未知错误 ${error.response.status}`;
}
} else if (error.request) {
message = '网络异常,请检查您的网络连接';
} else {
message = error.message;
}
Message({
message: message,
type: 'error',
duration: 5 * 1000
});
return Promise.reject(error);
}
);
// 封装GET请求
export function get(url, params = {}) {
return service({
url,
method: 'get',
params
});
}
// 封装POST请求
export function post(url, data = {}) {
return service({
url,
method: 'post',
data
});
}
// 封装PUT请求
export function put(url, data = {}) {
return service({
url,
method: 'put',
data
});
}
// 封装DELETE请求
export function del(url, params = {}) {
return service({
url,
method: 'delete',
params
});
}
export default service;
12. 总结
Axios是一个功能强大且易于使用的HTTP客户端库,它提供了许多便捷的功能,如拦截器、请求取消、进度监控等。通过合理的封装和配置,可以大大简化API请求的处理,提高开发效率。在实际项目中,建议根据项目需求对Axios进行适当的封装,统一处理错误,简化数据获取,使代码更加简洁和可维护。