Skip to content
1. 服务端返回了错误响应:
2. 请求已发出,但没有收到响应:
3. 请求设置阶段出错:
从第一个 GET 开始:获取并读取响应
Axios 通过一组请求方法别名提供调用入口。最简单的 GET 请求只需要把 URL 传给 axios.get(),它返回一个 Promise:
js
import axios from 'axios';
axios.get('https://api.example.com/users')
.then(response => {
console.log(response.data);
});response 是一个 AxiosResponse 对象,包含以下常用字段:
data:服务端返回的数据,已经过 JSON 解析status:HTTP 状态码,例如 200statusText:状态文本,例如'OK'headers:响应头config:本次请求实际使用的配置request:底层请求对象
大多数场景下只需要读取 data。使用 async/await 可以这样写(await 只能在 async 函数中使用):
js
const response = await axios.get('https://api.example.com/users');
const { data } = response;
console.log(data);data 是服务端返回数据经过 JSON 解析后的结果。如果接口返回的是一个分页对象,例如 { list: [], total: 0 },还需要再往下取一层:
js
const { data } = await axios.get('https://api.example.com/users');
console.log(data.list);
console.log(data.total);用解构可以直接把 data 从响应中取出来,后面的示例都采用这种写法。
POST 请求:把数据放到 body 中
POST 请求的数据放在请求体(body)中。axios.post(url, data) 的第二个参数会作为请求体发送:
js
const { data } = await axios.post('https://api.example.com/users', {
name: 'Alice',
email: 'alice@example.com'
});axios 默认会把 JavaScript 对象序列化为 JSON,同时设置 Content-Type: application/json。服务端收到的请求体就是一段 JSON 字符串。
如果请求体本身不是对象,也可以直接传字符串或 FormData:
js
await axios.post('https://api.example.com/log', 'raw text');在浏览器环境中,传入 FormData 实例时 axios 不会手动设置 Content-Type,而是由浏览器自动生成带 boundary 的 multipart 请求头。在 Node.js 环境中则不同:使用 form-data 包时需要手动设置 Content-Type: multipart/form-data,可以通过该包的 getHeaders() 方法获取。
params 与 data:query 和 body 的分工
GET 请求通常没有 body,查询参数拼在 URL 后面;POST/PUT/PATCH 请求则可能同时包含 query 和 body。
axios 在请求配置中把二者分开:
params:拼接到 URL 查询字符串中的参数data:作为请求体发送的数据
例如一个带查询条件的用户列表 GET 请求:
js
const { data } = await axios.get('https://api.example.com/users', {
params: {
page: 1,
pageSize: 20,
keyword: 'alice'
}
});实际发出的 URL 是:
https://api.example.com/users?page=1&pageSize=20&keyword=alice手动拼接 URL 也能达到同样效果,但使用 params 可以让参数序列化工作由 axios 完成。数组参数也会被正确编码:
js
await axios.get('/users', {
params: {
roles: ['admin', 'editor']
}
});axios 默认对数组使用 [] 后缀,序列化为:
roles[]=admin&roles[]=editor如果需要其他序列化方式,可以在 paramsSerializer 中自定义。
对于 POST/PUT/PATCH,params 仍然表示 URL 查询参数,data 才表示请求体:
js
await axios.post('/users', {
name: 'Alice'
}, {
params: {
source: 'web'
}
});上面的请求会发送到 /users?source=web,body 是 { "name": "Alice" }。
一个容易混淆的地方是:HTTP 协议本身并不禁止 GET 携带 body,但 axios 的 get 方法签名是 get(url, config),没有专门放 data 的参数。如果确实需要 GET 携带 body,可以写成:
js
await axios.get('/search', {
data: { query: 'axios' }
});不过大多数服务端和代理并不会读取 GET 的 body,实际应用中很少这样用。
常用方法速查:GET / POST / PUT / PATCH / DELETE
axios 为每个 HTTP 方法提供了对应的调用方式:
| 方法 | 调用形式 | 参数位置 |
|---|---|---|
| GET | axios.get(url, config) | query 用 config.params |
| POST | axios.post(url, data, config) | body 用 data,query 用 config.params |
| PUT | axios.put(url, data, config) | body 用 data,query 用 config.params |
| PATCH | axios.patch(url, data, config) | body 用 data,query 用 config.params |
| DELETE | axios.delete(url, config) | query 用 config.params,body 也可用 config.data |
DELETE 比较特殊。许多服务端接受 DELETE 请求带请求体,但 axios.delete 的第二个参数是 config,不是 data。若要发送 body,需要写在 config.data 中:
js
await axios.delete('/users/123', {
data: { reason: 'spam' }
});如果只是删除资源,通常只需要路径参数:
js
await axios.delete(`/users/${userId}`);PUT 和 PATCH 都放在 data 中,区别在语义上:PUT 通常表示完整替换,PATCH 表示部分更新。axios 对二者的请求构造方式完全相同。
js
// PUT:完整更新
await axios.put('/users/123', {
name: 'Alice',
email: 'alice@example.com'
});
// PATCH:只更新 email
await axios.patch('/users/123', {
email: 'new@example.com'
});错误处理:AxiosError 的三种常见场景
请求并不总是成功。当服务端返回 4xx/5xx 状态码,或者网络本身发生错误时,axios 返回的 Promise 会进入 rejected 状态。此时抛出的错误对象是 AxiosError。
在 try/catch 中,可以根据错误对象的属性判断失败原因。常见场景有三种。
1. 服务端返回了错误响应:error.response
只要服务端返回了任何 HTTP 状态码,axios 就会把该响应封装到 error.response 中。即使状态码是 500 或 404,error.response 也存在,且包含 data、status、headers 等字段。
js
try {
await axios.get('/users/not-exist');
} catch (error) {
if (error.response) {
console.log(error.response.status); // 404
console.log(error.response.data); // 服务端返回的错误内容
}
}2. 请求已发出,但没有收到响应:error.request
如果请求发送后,网络中断、服务端无响应、跨域失败或请求被取消,axios 无法获得响应对象。此时 error.request 存在,而 error.response 为 undefined。请求被取消时是否包含 error.request 取决于取消发生的时机:如果取消发生在请求发出之后,error.request 仍然存在;如果发生在发出之前,则可能落入第三种场景。
在浏览器中,error.request 是一个 XMLHttpRequest 实例;在 Node.js 中,是一个 http.ClientRequest 实例。
js
try {
await axios.get('/users/not-exist');
} catch (error) {
if (error.request) {
// 请求已经发出,但没有收到响应
console.log('No response received');
}
}3. 请求设置阶段出错:error.message
如果错误既没有 response 也没有 request,说明请求在发出前就失败了。例如配置项不合法、参数类型错误,或者请求在尚未发出时被取消。这类错误只能通过 error.message 查看原因。
js
try {
await axios.get('/users/not-exist');
} catch (error) {
if (!error.response && !error.request) {
// 请求设置阶段出错
console.log(error.message);
}
}Axios 提供了 axios.isAxiosError(error) 静态方法,用来判断错误是否来自 axios:
js
import axios from 'axios';
try {
// ...
} catch (error) {
if (axios.isAxiosError(error)) {
// 是 axios 产生的错误
}
}需要注意:error.response.data 不一定是对象。当服务端返回的是纯文本或 HTML 时,data 就是字符串,此时直接访问 error.response.data.message 会得到 undefined,不会报错,但可能让错误提示失灵。更稳妥的做法是判断类型后再取值:
js
const data = error.response?.data;
const message =
data && typeof data === 'object' ? data.message : error.message;如果 data 是字符串,message 就是 undefined,可以再退回到 error.message 或状态码。
综合示例:一个带错误处理的请求函数
把上面的内容组合起来,写一个简单的请求函数。这个函数获取指定用户的信息,并把错误分类后返回,方便调用方统一处理:
js
import axios from 'axios';
async function fetchUser(id) {
try {
const { data } = await axios.get(`/users/${id}`);
return { ok: true, data };
} catch (error) {
if (!axios.isAxiosError(error)) {
return { ok: false, code: 'UNKNOWN_ERROR', message: error.message };
}
if (error.response) {
const responseData = error.response.data;
const message = responseData && typeof responseData === 'object'
? responseData.message
: error.message;
return {
ok: false,
code: 'SERVER_ERROR',
status: error.response.status,
message
};
}
if (error.request) {
return {
ok: false,
code: 'NETWORK_ERROR',
message: 'No response received'
};
}
return {
ok: false,
code: 'REQUEST_SETUP_ERROR',
message: error.message
};
}
}
async function main() {
const result = await fetchUser(1);
if (result.ok) {
console.log(result.data);
} else {
console.error(result.code, result.message);
}
}
main();这个函数没有把 Promise reject 继续向外抛,而是统一收敛成普通对象。这样在业务代码中调用时,不需要每一处都写 try/catch,直接判断 result.ok 即可。
也可以使用 Promise 链式写法,不用 async/await,直接使用 .then/.catch:
js
axios.get('/users/1')
.then(response => {
console.log(response.data);
})
.catch(error => {
if (axios.isAxiosError(error)) {
// 按 error.response / error.request 区分处理
}
});两种写法在 axios 中都能工作。async/await 让代码看起来更像同步逻辑,而 .then/.catch 在需要并行请求或函数式组合时更直接。
有一点需要注意:示例中的 /users/${id} 是一个相对 URL。在浏览器中,相对路径会基于当前页面地址进行解析。但在 Node.js 环境中,axios 不会自动拼接域名,必须传入完整 URL,或者通过 axios.create() 设置 baseURL。
