Axios是一个基于Promise的HTTP库,可以发送get、post等请求,它作用于浏览器和Node.js中。当运行在浏览器时,使用XMLHttpRequest接口发送请求;当运行在Node.js时,使用HTTP对象发送请求。
第一步:安装axios 略
第二步:在项目中使用Axios时,通常的做法是先将Axios封装成一个模块,然后在组件中导入模块。
第三步:编写各种请求 这里只说明 基本的get请求和post请求。
request({
url: '请求路径',
method: 'get',
params: { 参数 }
}).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})
/**
* 发送GET请求
*/
export const getReq = (url, params) => {
return axios({
method: 'get',
params, // 使用params而非data
url: `${base}${url}`,
headers: {
'token': localStorage.getItem("token"),
}
});
}
使用它:
// 获取用户列表,带分页参数
getReq('/api/users', { page: 1, pageSize: 10 })
.then(res => {
console.log('用户列表:', res.data);
})
.catch(err => {
console.error('请求失败:', err);
});
request({
url: '请求路径',
method: 'post',
data: { 参数 }
}).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})
export const postReq = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
headers: {
'token': localStorage.getItem("token"),
}
});
export const fetchData = async (url, params) => {
try {
const response = await axios({
method: 'get',
params, // 修正:使用 params 而非 data
url: `${base}${url}`,
headers: {
'token': localStorage.getItem('token'),
}
});
return response.data;
} catch (error) {
console.error('请求失败:', error);
throw error; // 修正:重新抛出错误,让调用者处理
}
};
async/await 是一种建立在Promise之上的编写异步或非阻塞代码的新方法。async 是异步的意思,而 await 是 async wait的简写,即异步等待。
所以从语义上就很好理解 async 用于声明一个 函数 是异步的,而await 用于等待一个异步方法执行完成。
那么想要同步使用数据的话,就可以使用 async+await 。
说明:async函数返回的是一个 Promise 对象。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 一个直接量,async 会把这个直接量通过promise.solve() 封装成 Promise 对象。
如果 async 函数没有返回值, 它会返回 promise.solve(underfined)。
await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值(换句话说,await 可以等任意表达式的结果)。
如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
Promise 链式调用:.then().catch() 同步风格的
await:在 async 函数内部使用
.then()
和 .catch()
链式调用import { fetchData } from './api'; // 假设从 api.js 导入
// 调用 fetchData 获取用户列表
fetchData('/api/users', { page: 1, pageSize: 10 })
.then(data => {
console.log('用户列表:', data);
// 处理返回的数据(如更新组件状态)
})
.catch(error => {
console.error('请求失败:', error);
// 显示错误消息(如弹框提示)
});
//其他逻辑会和fetchData同步进行
.....
async
函数内部使用 await
async function loadUsers() {
try {
// 等待请求完成并获取数据
const data = await fetchData('/api/users', { page: 1, pageSize: 10 });
console.log('用户列表:', data);
// 可以直接使用同步风格的代码处理数据
const firstUser = data.list[0];
console.log('第一个用户:', firstUser);
} catch (error) {
console.error('请求失败:', error);
// 错误处理逻辑
}
}
// 调用 async 函数
loadUsers();
当执行 loadUsers()
函数时,它会返回一个 Promise 对象,并且其内部逻辑会以异步方式执行。以下是详细解释:
原因:任何使用 async
关键字声明的函数都会自动返回一个 Promise。
示例验证:
javascript
const result = loadUsers();
console.log(result instanceof Promise); // 输出: true
Promise 的状态:
fetchData
请求成功且没有抛出异常时,Promise 会 resolve,并传递 loadUsers
函数的返回值(若没有显式返回,默认返回 undefined
)。fetchData
抛出异常,或 loadUsers
内部 try
块中的代码报错时,Promise 会 reject,并传递错误对象。javascript
console.log('开始执行');
loadUsers();
console.log('结束执行');
// 输出顺序:
// 开始执行
// 结束执行
// (等待 fetchData 请求完成后)
// 用户列表: ...
// 第一个用户: ...
loadUsers()
函数被调用后立即返回 Promise,不会阻塞后续代码执行。await fetchData(...)
仅暂停函数内部的执行,不会影响外部代码(如 console.log('结束执行')
会先于 fetchData
的结果输出)。fetchData
的 Promise 解决(成功 / 失败)时,loadUsers
内部的 await
会恢复执行,并决定 Promise 的最终状态。当 fetchData
请求成功且 try
块内代码无异常时:
loadUsers
的 Promise 会 resolve,返回值为 undefined
(因为函数没有显式 return
)。
等价于:
javascript
async function loadUsers() {
// ... 代码 ...
return undefined; // 隐式返回
}
可通过 .then()
捕获结果:
javascript
loadUsers().then(result => {
console.log('loadUsers 返回值:', result); // 输出: undefined
});
当出现以下情况时,loadUsers
的 Promise 会 reject:
fetchData
抛出错误:
javascript
fetchData('/api/users', { page: 1 })
.catch(error => {
throw new Error('请求失败: ' + error); // 被 loadUsers 的 catch 捕获
});
try
块内其他代码报错:
javascript
const firstUser = data.list[0]; // 若 data.list 为 undefined,会抛出 TypeError
catch
块中重新抛出错误:
javascript
catch (error) {
console.error('请求失败:', error);
throw error; // 重新抛出,导致 Promise reject
}
.catch()
捕获错误: javascript
loadUsers().catch(error => {
console.error('loadUsers 错误:', error);
});
loadUsers
函数的异步逻辑等价于以下 Promise 写法:
javascript
function loadUsers() {
return fetchData('/api/users', { page: 1, pageSize: 10 })
.then(data => {
console.log('用户列表:', data);
const firstUser = data.list[0];
console.log('第一个用户:', firstUser);
// 隐式返回 undefined
})
.catch(error => {
console.error('请求失败:', error);
throw error; // 重新抛出错误,保持 Promise 链的异常传递
});
}
.then()
javascript
loadUsers()
.then(() => {
console.log('数据处理完成');
})
.catch(error => {
console.error('处理失败:', error);
});
async
函数中使用 await
javascript
async function processData() {
try {
await loadUsers(); // 等待 loadUsers 的 Promise 解决
console.log('loadUsers 执行完毕');
} catch (error) {
console.error('processData 捕获到错误:', error);
}
}
loadUsers()
始终返回一个 Promise 对象。fetchData
正常返回且无代码错误):Promise resolve,返回 undefined
。fetchData
报错或代码异常):Promise reject,传递错误对象。await
暂仅停自身执行,不阻塞主线程,整体仍为异步操作。export const postRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
transformRequest: [function (data) {
let ret = '';
for (let key in data) {
ret += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&';
}
return ret;
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded', // 修正为表单格式
}
});
}
数据格式与请求头的关系:
application/json
:请求体应为 JSON 格式(如{"key": "value"}
)。application/x-www-form-urlencoded
:请求体应为表单格式(如key=value&key2=value2
)。transformRequest
的影响:
transformRequest
并保持application/json
头。正确的搭配方式:
数据格式 | Content-Type | 是否需要 transformRequest |
---|---|---|
JSON | application/json | 不需要 |
表单数据 | application/x-www-form-urlencoded | 需要(如当前函数) |
二进制文件 / 表单 | multipart/form-data | 不需要 |
import { postRequest } from './api.js'; // 导入函数
// 表单数据
const formData = {
username: 'test_user',
password: '123456',
email: '[email protected]'
};
// 调用函数
postRequest('/api/register', formData)
.then(response => {
console.log('注册成功:', response.data);
})
.catch(error => {
console.error('注册失败:', error);
});
如果需要发送 JSON 数据,应使用以下封装:
export const postJsonRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
headers: {
'Content-Type': 'application/json',
}
});
}
// 调用示例
const userData = {
name: '张三',
age: 25,
hobbies: ['阅读', '编程']
};
postJsonRequest('/api/users', userData)
.then(res => console.log(res.data));
参数说明:
url
:API 路径(如/api/login
),会自动拼接base
(如http://localhost:8080
)。params
:需要发送的数据对象,会被transformRequest
转换为表单格式。错误处理:
.catch()
处理请求失败: postRequest(...).catch(error => {
const status = error.response?.status || '网络错误';
const message = error.response?.data?.message || '请求失败';
console.error(`状态码 ${status}: ${message}`);
});
与其他请求函数的区别:
{key: value}
)application/x-www-form-urlencoded
)如果需要发送 JSON 数据,最好创建专门的函数,不需要transformRequest
。
场景 | 推荐注解 | 示例 |
---|---|---|
处理 JSON 数据 | @RequestBody |
@RequestBody User user |
处理简单表单数据(少量参数) | @RequestParam |
@RequestParam("username") String name |
处理复杂表单数据(对象绑定) | @ModelAttribute |
@ModelAttribute User user |
同时支持 JSON 和表单(需自定义) | @RequestBody + 转换器 |
配置 FormHttpMessageConverter |
建议:
@RequestBody
,前端发送 application/json
。@RequestParam
或 @ModelAttribute
,前端发送 application/x-www-form-urlencoded
。@RequestBody
同时处理两种格式,会增加复杂度。export const postJsonRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params, // axios 自动将对象序列化为 JSON
headers: {
'Content-Type': 'application/json',
}
});
}
调用方式例子:
// 发送用户数据
const userData = {
username: 'john',
email: '[email protected]',
isActive: true
};
postJsonRequest('/api/users', userData)
.then(res => console.log('用户创建成功:', res.data))
.catch(err => console.error('错误:', err));
export const postFormRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
transformRequest: [function (data) {
let ret = '';
for (let key in data) {
ret += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&';
}
return ret;
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
});
}
调用方式例子:
// 提交登录表单
const loginData = {
username: 'admin',
password: '123456',
rememberMe: true
};
postFormRequest('/api/login', loginData)
.then(res => {
localStorage.setItem('token', res.data.token);
console.log('登录成功');
})
.catch(err => alert('登录失败: ' + err.message));
方案 | Content-Type | 数据格式 | 后端适配 | 前端写法 |
---|---|---|---|---|
方案一(JSON) | application/json |
{"key":"value"} |
Spring Boot 的 @RequestBody |
直接传递对象 |
方案二(表单) | application/x-www-form-urlencoded |
key=value&key2=value2 |
Spring Boot 的 @RequestParam /@ModelAttribute |
需手动或用库序列化 |
后端接口匹配:
@RequestBody
注解@RequestParam
或 @ModelAttribute
编码问题:
encodeURIComponent
自动编码\u4e2d
)export const putRequest = (url, params) => {
return axios({
method: 'put',
url: `${base}${url}`,
data: params,
transformRequest: [function (data) {
if (!data) return '';
const ret = [];
for (let key in data) {
if (data.hasOwnProperty(key)) {
const value = data[key];
// 处理值为 null 或 undefined 的情况
const encodedValue = value === null || value === undefined ? '' : encodeURIComponent(value);
ret.push(`${encodeURIComponent(key)}=${encodedValue}`);
}
}
// 使用 join 避免末尾多余的 &
return ret.join('&');
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.catch(error => {
console.error('PUT 请求失败:', error);
// 可以在这里进行统一的错误处理
throw error; // 继续抛出错误,让调用者可以捕获
});
};
参考vue+element UI 学习总结笔记(一)_vue+elementui一点-CSDN博客