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