的核心原理Axios是一个基于promise的HTTP库,可以自动判断当前环境,自由切换浏览器和node.js环境。如果是浏览器,会基于XMLHttpRequests实现;如果是node环境,会基于node内置的核心http模块来实现。同时,它还用promise处理响应结果,避免陷入回调地狱。不仅如此,axios还可以拦截请求和响应,转换请求数据和响应数据,中断请求,自动转换JSON数据,支持客户端防御XSRF等等,还有这么多好用的功能,一起来看看吧它是如何实现的!一、基本使用axios的基本使用方法主要有:axios(config)axios.method(url,data,config)//发送POST请求axios({method:'post',url:'/user/12345',data:{username:'Web前端严选',age:2}});//GET请求ID参数axios.get('/user?ID=12345').then(function(response){console.日志(响应);})。捕获(函数(错误){console.log(错误);});2、从axios(config)实现axios从使用上可以看出,导出的axios是一个方法。从axios.get()的使用可以看出导出的axios原型会有get、post、put、delete等方法。经分析,axios其实是axios类中的一个方法。我们可以先写一个request方法来实现主要的请求功能,这样就可以通过axios(config)的形式调用了。classAxios{constructor(){}request(config){returnnewPromise((resolve)=>{const{url='',data={},method='get'}=config;//解构并传递参数constxhr=newXMLHttpRequest;//创建请求对象xhr.open(method,url,true);xhr.onreadystatechange=()=>{if(xhr.readyState==4&&xhr.status==200){resolve(xhr.responseText);//asynchronous请求返回后,将Promise转为成功状态,并导出结果}}xhr.send(JSON.stringfy(data));})}}functionCreateAxiosFn(??){letaxios=newAxios;letreq=axios.request.绑定(axios);returnreq;}letaxios=CreateAxiosFn(??);然后构建一个简单的服务器代码来测试请求的效果:constexpress=require('express')letapp=express();app.all('*',function(req,res,next){res.header('Access-Control-Allow-Origin','*');res.header('Access-Control-Allow-Headers','Content-Type');res.header('Access-Control-Allow-Methods','*');res.header('Content-Type','application/json;charset=utf-8');next();});app.get('/getInfo',function(request,response){letdata={'username':'前端选择','age':'2'};response.json(data);});app.listen(3000,function(){console.log("serverstart");});启动服务器服务结束后,在页面中测试请求是否成功:点击点击按钮后,可以看到请求成功,获取到数据3.原型上的方法接下来以axios.method()的形式实现方法。通过axios.get()、axios.post()、axios.put()等方法可以看出,都是axios.prototype上的方法。这些方法可以调用内部请求方法:constmethodsArr=['get','post','put','delete','head','options','patch','head'];methodsArr.forEach(method=>{Axios.prototype[method]=function(){returnthis.request({method:method,...arguments[0]})}})arguments的第一个参数包含url等信息,data等。可以直接解构它的第一个元素。还需要实现一个工具方法,使用将b方法属性混入a中:constutils={extend(a,b,context){for(letkeyinb){if(b.hasOwnProperty(key)){if(typeofb[key]=='function'){a[key]=b[key].bind(context);}else{a[key]=b[key]}}}}}最后导出了axios的request方法,所以它有get,post等方法再次测试post请求:axios.post({url:'http://localhost:3000/postTest',data:{a:1,b:2}}).then(res=>{console.log(res);})可以看到结果正确返回了。4.拦截器下面看一下拦截器的使用://请求拦截axios.interceptors.request.use(function(config){//发送请求前returnconfig;},function(error){//请求错误处理returnPromise.reject(error);});//响应拦截axios.interceptors.response.use(function(response){//响应数据处理returnresponse;},function(error){//响应错误处理returnPromise.reject(错误);});拦截器,顾名思义,就是在请求之前和响应之前拦截并处理实际要执行的操作数据。那么如何实现呢,首先,拦截器也是一个管理响应和请求的类。classInterceptorsManage{constructor(){this.handlers=[];}use(onFulField,onRejected){//在队列中存储成功和失败的回调this.handlers.push({onFulField,onRejected})}}axios.interceptors.response.use和axios.interceptors.request.use定义请求和响应的拦截方法。这说明axios上有响应拦截器和请求拦截器,那么在axios上如何实现:classAxios{constructor(){this.interceptors={request:newInterceptorsManage,response:newInterceptorsManage}}//....}在构造函数中添加拦截器属性,然后定义请求和响应属性,用于处理请求和响应。use方法执行时,传入的回调函数会放在handlers数组中。这时候回过头来看使用方法,axios.interceptors.request.use方法绑定了axios实例,所以也需要将axios上的属性和方法传递给request,挂载拦截器对象到请求方法。functionCreateAxiosFn(??){letaxios=newAxios();letreq=axios.request.bind(axios);utils.extend(req,Axios.prototype,axios)//添加如下代码utils.extend(req,axios)returnreq;}但是现在request不仅要执行请求的发送,还要执行拦截器中handler的回调函数,所以需要修改请求方法:request(config){//interceptorandrequestqueueletchain=[this.sendAjax.bind(this),undefined];//请求的拦截this.interceptors.request.handlers.forEach(interceptor=>{chain.unshift(interceptor.onFulField,interceptor.onRejected);})//拦截响应this。interceptors.response.handlers.forEach(interceptor=>{chain.push(interceptor.onFulField,interceptor.onRejected)})letpromise=Promise.resolve(config);while(chain.length>0){//从头开始依次进行请求拦截、真实请求、响应拦截url='',method='get',data={}}=config;constxhr=newXMLHttpRequest();xhr.open(method,url,true);xhr.onreadystatechange=()=>{if(xhr.readyState==4&&xhr.status==200){resolve(xhr.responseText)}}xhr.send(JSON.stringify(data));})}chain最后执行的时候是这样的:chain=[//请求前成功回调和失败回调function(config){returnconfig;},function(error){returnPromise.reject(error);}//真正的请求执行this.sendAjax.bind(this),undefined,//请求后响应的成功回调和失败回调function(response){returnresponse;},function(error){returnPromise.reject(error);}]在请求之前,promise执行为:promise.then(function(config){returnconfig;},function(error){returnPromise.reject(error);})当请求执行后响应为:promise.then(this.sendAjax.bind(this),undefined,),执行为:promise.then(function(response){returnresponse;},function(error){returnPromise.reject(error);})这个时候我们来测试拦截器的使用:functiongetMsg(){axios.interceptors.request.use((config)=>{console.log('请求拦截:',配置);returnconfig;},err=>{returnPromise.reject(err)})axios.interceptors.response.use(response=>{response={message:'响应数据替换',data:response}returnresponse},err=>{console.log(err,'response错误')returnPromise.reject(err)})axios.get({url:'http://localhost:3000/getTest',}).then(res=>{console.log(res);})}在控制台可以看到拦截过程的打印输出,证明拦截成功!5.总结axios天生就支持Promise的性能方便异步处理,同时利用Promise拦截请求,使得用户在请求过程中可以添加更多的功能,以及在请求时可以自由操作的思想《请求被打断》清新简单,不落俗套,具有很好的参考价值。看完这篇文章,你明白axios的核心原理了吗?本文转载自微信公众号“Web前端严选”,可通过以下二维码关注。转载本文请联系web前端严选公众号。