设为首页 - 加入收藏  
您的当前位置:首页 >人工智能 >手写Axios核心原理 正文

手写Axios核心原理

来源:汇智坊编辑:人工智能时间:2025-11-03 17:08:32

Axios是手写一个基于promise的HTTP库,它能够自动判断当前环境,心原自由切换在浏览器和 node.js环境中。手写如果是心原浏览器,就会基于XMLHttpRequests实现;如果是手写node环境,就会基于node内置核心http模块实现。心原同时,手写它还用promise处理了响应结果,心原避免陷入回调地狱中去。手写

不仅如此,心原Axios还可以拦截请求和响应、手写转化请求数据和响应数据、心原中断请求、手写自动转换JSON数据、心原客户端支持防御XSRF等。手写如此众多好用的功能,快来一起看看它是如何实现的吧!

1.基本使用

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.log(response);   })   .catch(function (error) {     console.log(error);   }); 

2.实现axios

从axios(config)的使用上可以看出导出的axios是一个方法,从axios.get()的使用上可以看出导出的axios原型上会有get,post,put,delete等方法。

由分析可知,axios实际上是Axios类中的一个方法。高防服务器我们可以先写一个request方法来实现主要的请求功能,这样就能使用axios(config)形式来调用了。

class Axios{     constructor(){     }     request(config){         return new Promise((resolve) => {             const {url=,data={},method=get} = config; //解构传参             const xhr = new XMLHttpRequest;     //创建请求对象             xhr.open(method,url,true);              xhr.onreadystatechange = () => {                 if(xhr.readyState == 4 && xhr.status == 200){                     resolve(xhr.responseText);                     //异步请求返回后将Promise转为成功态并将结果导出                 }             }             xhr.send(JSON.stringfy(data));         })     } } function CreateAxiosFn(){     let axios = new Axios;     let req = axios.request.bind(axios);     return req; } let axios = CreateAxiosFn(); 

然后搭建一个简易服务端代码,以测试请求的效果:

const express = require(express) let app = 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){     let data = {         username:前端严选,         age:2     };     response.json(data); }); app.listen(3000, function(){     console.log("服务器启动"); }); 

启动服务后,在页面中测试请求是否成功:

<button onclick="getMsg()">点击</button> <script src="./axios.js"></script> <script>     function getMsg(){         axios({             method: get,             url: http://localhost:3000/getInfo         }).then(res => {             console.log(res);         })     } </script> 

点击按钮后,可以看到请求成功并获取到数据。

3.原型上的方法

接下来实现以axios.method()形式的方法。

通过axios.get(),axios.post(),axios.put()等方法可以看出它们都是Axios.prototype上的方法,这些方法调用内部的request方法即可:

const methodsArr = [get,post,put,delete,head,options,patch,head]; methodsArr.forEach(method => {     Axios.prototype[method] = function(){         return this.request({             method: method,             ...arguments[0]         })     } }) 

arguments的第一个参数包含url,data等信息,直接解构它的第一个元素即可

还需要实现一个工具方法,用来将b方法属性混入到a中去:

const utils = {     extend(a,b,context){         for(let key in b){             if(b.hasOwnProperty(key)){                 if(typeof b[key] == function){                     a[key] = b[key].bind(context);                 }else{                     a[key] = b[key]                 }             }         }     } } 

最终导出axios的request方法,使之拥有get,post等方法

function CreateAxiosFn(){     let axios = new Axios;     let req = axios.request.bind(axios);     //新增如下代码     utils.extend(req, Axios.prototype, axios)     return req; } 

再来测试一下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) {     // 在发送请求之前     return config;   }, function (error) {     // 请求错误处理     return Promise.reject(error);   }); // 响应拦截 axios.interceptors.response.use(function (response) {     // 响应数据处理     return response;   }, function (error) {     // 响应错误处理     return Promise.reject(error);   }); 

拦截器,顾名思义就是在请求之前和响应之前,对真正要执行的操作数据拦截住进行一些处理。

那么如何实现呢,免费信息发布网首先拦截器也是一个类,用于管理响应和请求。

class InterceptorsManage{     constructor(){         this.handlers = [];     }     use(onFulField,onRejected){         //将成功的回调和失败的回调都存放到队列中         this.handlers.push({             onFulField,             onRejected         })     } } 

axios.interceptors.response.use和axios.interceptors.request.use来定义请求和响应的拦截方法。

这说明axios上有响应拦截器和请求拦截器,那么如何在axios上实现呢:

class Axios{     constructor(){         this.interceptors = {             request: new InterceptorsManage,             response: new InterceptorsManage         }     }     //.... } 

在Axios的构造函数中新增interceptors属性,然后定义request和response属性用于处理请求和响应。

执行use方法时,会把传入的回调函数放到handlers数组中。

这时再回看使用方式,axios.interceptors.request.use方法是绑在axios实例上的,因此同样需要把Axios上的属性和方法转移到request上,将interceptors对象挂载到request方法上。

function CreateAxiosFn() {   let axios = new Axios();   let req = axios.request.bind(axios);   utils.extend(req, Axios.prototype, axios)   //新增如下代码   utils.extend(req, axios)   return req; } 

但是现在request不仅要执行请求的发送,还要执行拦截器中handler的回调函数,因此还需要把request方法进行一下改造:

request(config){     //拦截器和请求的队列     let chain = [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)     })     let promise = Promise.resolve(config);     while(chain.length > 0){         //从头部开始依次执行请求的拦截、真正的请求、b2b信息网响应的拦截         promise = promise.then(chain.shift(),chain.shift());     }     return promise; } sendAjax(config){     return new Promise((resolve) => {         const {url=,method=get,data={}} = config;         const xhr = new XMLHttpRequest();         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) {         return config;     },      function (error) {         return Promise.reject(error);     }  //真正的请求执行     this.sendAjax.bind(this),      undefined,  //请求之后响应的成功回调和失败回调     function (response) {         return response;     },      function (error) {         return Promise.reject(error);     } ] 

请求之前,promise执行为:

promise.then(  function (config) {         return config;     },      function (error) {         return Promise.reject(error);     } ) 

请求时,执行为:

promise.then(  this.sendAjax.bind(this),      undefined, ) 

响应后,执行为:

promise.then(  function (response) {         return response;     },      function (error) {         return Promise.reject(error);     } ) 

这时我们测试一下拦截器的使用:

function getMsg(){     axios.interceptors.request.use((config) => {         console.log(请求拦截:,config);         return config;     },err => {         return Promise.reject(err)     })     axios.interceptors.response.use(response => {         response = {             message: 响应数据替换,             data: response         }         return response     },err => {         console.log(err,响应错误)         return Promise.reject(err)     })     axios.get({         url: http://localhost:3000/getTest,     }).then(res => {         console.log(res);     }) } 

可以在控制台中看到拦截处理的打印输出,证明拦截成功!

5.总结

Axios天然支持Promise的性能让其方便对异步进行处理,同时又利用了Promise对请求进行了拦截,使得用户可以在请求过程中添加更多的功能,对请求的中断能自如操作。它的思想既清新朴实又不落入俗套,具有很好的借鉴意义。

看完这篇文章,你了解了Axios的核心原理了吗?

本文转载自微信公众号「Web前端严选」,可以通过以下二维码关注。转载本文请联系Web前端严选公众号。

0.1235s , 11754.15625 kb

Copyright © 2025 Powered by 手写Axios核心原理,汇智坊  滇ICP备2023006006号-2

sitemap

Top