2022年10月11日,在《AXAJ与JavaScript中的异步编程元素》文章中我总结了对于前端开发者中需要了解和掌握的8种异步编程元素,其中XMLHTTPRequest很关键,它是原生JavaScript提供的用于发送 HTTP 请求的对象,用于在前端与服务器进行数据交互。
XMLHTTPRequest提供了基本的网络请求功能,但使用起来相对繁琐,需要编写大量的代码来处理不同阶段的请求、响应和错误,即使这些对这些处理做了很好的封装也一样。
曾经很流行的JQuery中的AXAJ就是对XMLHTTPRequest进行了很好的封装,让开发者能够很方便灵活地使用。
随着JQuery逐渐淡出,axios在很多前端框架中占据了主流(比如vue+elementUI框架),它也是对XMLHttpRequest(在Node.js 环境中封装的是http模块)进行了很好的封装,提供了一个更为优雅和强大的接口来发送 HTTP 请求。axios基于Promise,允许开发人员以链式调用的方式处理 HTTP 响应的成功和失败情况,从而简化了异步代码的书写和流程控制。
一、axios的常用方法
1. 发送 GET 请求:axios.get(url[, config])。
2. 发送 POST 请求:axios.post(url[, data[, config]])。
3. 发送 PUT 请求:axios.put(url[, data[, config]])。
4. 发送 DELETE 请求:axios.delete(url[, config])。
5. 发送 HEAD 请求:axios.head(url[, config])。
6. 发送 OPTIONS 请求:axios.options(url[, config])。
7. 发送 PATCH 请求:axios.patch(url[, data[, config]])。
axios 提供的各种方法分别对应HTTP规范中定义的不同请求方法,它们各自有不同的用途,通常与 RESTful API 设计标准保持一致,也是为了让axios操作更加语义化。
对应的后端操作(NodeJS):
constexpress=require('express');
constmyapp=express();
myapp.get('/api',(req,res)=>{
//处理get请求
});
myapp.post('/api',(req,res)=>{
//处理post请求
});
myapp.put('/api',(req,res)=>{
//处理put请求
});
myapp.delete('/api',(req,res)=>{
//处理delete请求
});
myapp.patch('/api',(req,res)=>{
//处理patch请求
});
myapp.head('/api',(req,res)=>{
//处理head请求
});
myapp.options('/api',(req,res)=>{
//处理OPTIONS请求
});
在平常的开发中,我们经常使用的是get和post方法,通常是在这两个操作中完成对数据的增、删、改、查。
二、axios的编码范式
axios是一个基于Promise的HTTP客户端,在JavaScript代码中使用axios库时,有几种常见的编码范式。
以axios的get方法为例,下面是常见的用法。
⑴基本使用
axios.get('http://127.0.0.1:1234/user')
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.error(err);
});
axios({
url:'http://127.0.0.1:1234/user',
method:'get'
}).then(function (res) {
console.log(res);
})
.catch(function (err) {
console.error(err);
});
⑵带有参数
axios.get('http://127.0.0.1:1234/user', {
params: {
ID: 2
}
})
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.error(err);
});
axios({
url:'http://127.0.0.1:1234/user',
method:'get',
params: { ID: 2 }
})
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.error(err);
});
⑶通过async/await使用
async function getUserInfo() {
try {
const res = await axios.get('http://127.0.0.1:1234/user?ID=2');
console.log(res);
} catch (err) {
console.error(err);
}
}
getUserInfo();
⑷创建axios实例
const myAxios = axios.create({
baseURL: 'http://127.0.0.1:1234',
timeout: 2000,
});
myAxios.get('/user?ID=2')
.then(function (res) {
console.log(res);
}).catch(function (err) {
console.error(err);
});
三、axios的链式编程
很多前端开发者喜欢链式编程写法。
链式编程中如果任何一个请求发生错误,最后的catch方法都将捕获并统一处理错误,这是方便的地方,但是过多的链式编程给调试带来不必要的麻烦。
Mock.mock('http://127.0.0.1:1234/user?name=vue',{
'user':{'Id':1 }
})
Mock.mock('http://127.0.0.1:1234/user?userId=1',{
'info':{'title':'vue + elementUI + Admin' }
})
axios.get('http://127.0.0.1:1234/user?name=vue')
.then(function (res) {
return res.data.user.Id;
})
.then(function (userId) {
return axios.get('http://127.0.0.1:1234/user?userId='+userId);
})
.then(function (res) {
console.log(res.data.info.title);
})
.catch(function (err) {
console.err(err);
});
程序最后输出:vue + elementUI + Admin。
四、axios处理并发请求
Mock.mock('http://127.0.0.1:1234/getUserName',{
'name':'vue'
})
Mock.mock('http://127.0.0.1:1234/getUserInfo',{
'Framework':'vue + elementUI + Admin'
})
function getUserName() {
return axios.get('http://127.0.0.1:1234/getUserName');
}
function getUserInfo() {
return axios.get('http://127.0.0.1:1234/getUserInfo');
}
Promise.all([getUserName(), getUserInfo()])
.then(function (res) {
const arr1 = res[0];
const arr2 = res[1];
// 处理结果
console.log(arr1.data.name);
console.log(arr2.data.Framework);
});
axios.all([getUserName(), getUserInfo()])
.then(function (res) {
const arr1 = res[0];
const arr2 = res[1];
// 处理结果
console.log(arr1.data.name);
console.log(arr2.data.Framework);
});
如果不使用axios.all()或者Promise.all()来执行,让两个axios单独执行,那么可能由于axios完成时间的不同,导致不同的axios获取结果存在先后顺序;但是放在axios.all()或者Promise.all()中来执行,那么就是等待这两个都完成再一起输出结果。
现在流行的写法是使用箭头函数:
axios.all([getUserName(), getUserInfo()])
.then(res=>{
console.log(res);
for(let i=0;i<res.length;i++){
console.log(res[i].data);
}
});
或者:
axios.all([getUserName(), getUserInfo()])
.then(axios.spread(
(res1,res2) => {
console.log(res1.data.name);
console.log(res2.data.Framework);
}));
五、创建axios实例
一般写法:
const myAxios=axios.create();
myAxios.defaults.baseURL="http://127.0.0.1:1234";
myAxios.request({
method:'get',
url:'/user',
timeout: 2000,
headers: {'X-Custom-Header': 'foobar'}
}).then(
res=>{ console.log(res.data.name); }
)
或者:
const myAxios=axios.create({
baseURL:"http://127.0.0.1:1234",
timeout: 2000,
headers: {'X-Custom-Header': 'foobar'}
});
myAxios.request({
method:'get',
url:'/user',
}).then(
res=>{ console.log(res.data.name); }
)
六、axios拦截器
拦截操作就是在axios进行操作之前进行一些系统需要统一处理的操作,比如可以验证用户、检查请求的合法性、检查数据的完整性等等。
Mock.mock('http://127.0.0.1:1234/user',{
'name':'JavaScript'
})
const myAxios=axios.create({
baseURL:"http://127.0.0.1:1234",
timeout: 2000,
headers: {'X-Custom-Header': 'foobar'}
});
myAxios.interceptors.request.use(
request=>{
console.log("检查请求...");
return request
}
)
myAxios.interceptors.response.use(
response=>{
console.log("检查返回数据...");
return response
}
)
myAxios.request({
method:'get',
url:'/user',
}).then(
res=>{ console.log(res.data.name); }
)
上面执行的结果显示如下:
检查请求...
检查返回数据...
JavaScript