1. Axios
概述
Axios
是一个基于 Promise
的 HTTP
客户端库,专为浏览器和 Node.js
设计,用来发送AJAX
请求。可以通过npm install -g axios
安装axios
库。Axios
有以下特征:
- 跨平台兼容性:同一套代码可运行于浏览器和
Node.js
。在浏览器端使用XMLHttpRequest
,在Node.js
中则基于原生http
模块实现。 - 支持异步处理:所有请求均返回
Promise
对象,支持链式调用then()、catch()
和async
、await
语法。 - 拦截器机制:可在发送请求前统一处理,也可以对返回结果进行预处理。
- 自动化数据处理:自动将请求数据转换为
JSON
格式,并解析响应结果为JS
对象,无需手动处理。 - 取消请求:通过
AbortController
终止未完成的请求,优化资源利用。 - 并发请求:通过
axiosAll()
和axios.spread()
批量处理多个请求。 XSRF/CSRF
防御:自动从cookie
中读取xsrf-token
,并在请求头添加X-XSRF-TOKEN
。
2. Axios
的基本使用
2.1 Json-server
的使用
json-server
是一个可以基于一个 JSON
文件快速创建完整 RESTful API
的工具,适用于前端开发中用来模拟后端接口。可以通过npm install -g json-server
安装axios
库。
首先需要准备一个JSON
文件,如db.json
:
{
"posts": [
{ "id": 1, "title": "Hello JSON Server" },
{ "id": 2, "title": "Another Post" },
{ "id": 3, "title": "Hello Bruce" }
],
"comments": [
{ "id": 1, "body": "Nice!" }
]
}
然后通过json-server --watch db.json
启动服务,默认会运行在http://localhost:3000
。启动之后可以做如下操作:
方法 | 路径 | 说明 |
---|---|---|
GET |
/posts |
获取所有数据 |
GET |
/posts/1 |
获取 id=1 的数据 |
POST |
/posts |
添加数据 |
PUT |
/posts/1 |
替换数据 |
PATCH |
/posts/1 |
局部更新 |
DELETE |
/posts/1 |
删除数据 |
且json-server
还支持过滤和分页,如下:
/posts?title=Hello
:按字段查询/posts?_page=1&_limit=10
:分页
2.2 发送请求
首先是发送最常用的get
请求与post
请求,如下:
// get请求
import axios from "axios"
const test = () => {
axios.get('http://localhost:3000/posts', {
headers: {
// 设置请求头
'Content-Type': 'application/json',
'Authorization': 'Bearer your_token'
},
params: {
// 设置请求参数, 在json-server中_page和_limit用于分页
_page: 2,
_limit: 1
}
}).then(res => {
console.log(res.data)
}).catch(err => {
console.log(err)
})
}
import axios from "axios"
// 设置全局配置
axios.defaults.baseURL = 'http://localhost:3000'
axios.defaults.headers.post['Content-Type'] = 'application/json'
axios.defaults.timeout = 5000
const test = () => {
axios.post('/posts', {
id: 5,
title: 'Hello Test'
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
其它请求使用方法类似:
axios.put('/api/users/1', { name: 'Bob' }); // 全量更新
axios.patch('/api/users/1', { age: 30 }); // 局部更新
axios.delete('/api/users/1'); // 删除数据
axios
的返回结果res
如下:不难发现返回的数据都在res.data
中。
config: {transitional: {…}, adapter: Array(3), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}
data: {id: 5, title: 'Hello Test'}
headers: AxiosHeaders {content-length: '38', content-type: 'application/json'}
request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
status: 201
statusText: "Created"
在开发中直接使用axios
对象是不建议的,任意配置的修改都会影响到所有请求,因此可以使用axios.create()
创建独立实例来避免全局污染,它的使用方式和全局对象axios
几乎一致。
const http = axios.create({
baseURL: "http://localhost:3000",
headers: {
"Content-Type": "application/json",
},
...
});
http.get(...)
2.3 拦截器
拦截器分为请求拦截器和响应拦截器,如下:
- 请求拦截器:在请求发送前拦截,用于添加认证信息、修改请求头或参数。
- 响应拦截器:在响应返回后拦截,用于统一处理数据格式、错误状态码和日志记录。
其核心优势如下:
- 代码复用:全局处理通用逻辑如
Token
注入,避免重复代码。 - 错误集中管理:统一处理
401
未授权、500
服务器错误等状态码。 - 安全增强:自动防御
XSRF
攻击,支持请求参数加密。
请求拦截器和响应拦截器的使用如下:当有多个请求拦截器和响应拦截器时,请求拦截器先进后出,响应拦截器先进先出。
// 创建axios使用
import axios from 'axios';
const service = axios.create({
baseURL: 'http://api.example.com',
timeout: 5000, // 超时时间
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 添加 Token
if (config.url !== '/login') {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
}
// 添加公共参数, 如API版本号
config.params = { ...config.params, api_version: '1.0' };
return config;
}, (error) => {
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 提取后端核心数据,假设结构为 { code: 200, data: {} }
if (response.data.code === 200) {
return response.data.data[6,10];
} else {
return Promise.reject(response.data);
}
}, (error) => {
// 统一错误处理
if (error.response) {
switch (error.response.status) {
case 401:
localStorage.removeItem('token');
router.push('/login'); // 跳转登录页
break;
case 500:
alert('服务器错误,请稍后重试');
break;
}
}
return Promise.reject(error);
}
);
2.4 取消请求
使用json-server
模拟请求耗时2s
后获取服务器数据,如下:
json-server --watch db.json --d 2000
import axios from "axios"
const controller = new AbortController();
const signal = controller.signal;
const test = () => {
axios.get('/posts', {
signal
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
const cancelTest = () => {
// 取消请求
controller.abort();
}