内容简介:如果大家有了解过
源码架构
- 创建一个
Axios
构造函数,添加默认配置,拦截器,原型上挂载请求方法
// core/axios.js // 构造Axios构造函数 function Axios(instanceConfig) { this.defaults = instanceConfig; // 添加拦截器 this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager() }; } // 实际请求方法 Axios.prototype.request = function() {}; Axios.prototype.getUri = function() {}; // 没有请求体 delete get head options Axios.prototype.get = function(url, config = {}) { return this.request(Object.assign(config, { method: 'get', url })) }; // 有请求体 post put patch Axios.prototype.post = function(url, data, config = {}) { return this.request(Object.assign(config, { method: 'post', url, data })) }; 复制代码
- 实例化一个
Axios
实例context
,接着创建instance
指向Axios.prototype.request
方法,并绑定了上下文context
; - 通过
extend
方法把context
中的原型方法和实例方法全部拷贝到instance
上 ,返回instance
- 创建一个默认实例,挂载快捷方法
create
,CancelToken
,all
等方法
// axios.js // 创建一个Axios实例,挂载辅助方法,并导出该混合对象 function createInstance(defaultConfig = {}) { var context = new Axios(defaultConfig); var instance = bind(Axios.prototype.request, context); // Copy axios.prototype to instance utils.extend(instance, Axios.prototype, context) // copy context to instance utils.extend(instance, context) return intance } // create the default instance to be exported var axios = createInstance({}) axios.Axios = Axios axios.create= function(config) { return createInstance(Object.assign(axios.defaults, config)) } // 取消请求 axios.Cancel = require('./cancel/Cancel') axios.CancelToken = require('./cancel/CancelToken') axios.isCancel = require('./cancel/isCancel') // Prmoise.all 的语法糖 axios.all = Promise.all axios.spread = require('./helpers/spread') 复制代码
如何实现 axios
所支持的的功能
支持 Node
和 浏览器
端的 http
请求
-
关键代码
-
原理介绍
- 通过
process
区分出Node
环境和浏览器环境 - 浏览器环境使用
XMLHttpRquest
发起http请求,Node环境使用http
,https
模块发起请求 - 通过
Promise
包装实现请求方法
- 通过
请求响应拦截器
-
关键代码
- lib/core/InterceptorManager.js
- lib/core/Axio.js
-
拦截器运行示意
Promise .then(request[1].fulfilled, request[1].rejected) .then(request[0].fulfilled, request[1].rejected) .then(dispatchRequest, undefined) .then(response[0].fulfilled, response[0].rejected) .then(response[1].fulfilled, response[1].rejected) .then() // user opt 复制代码
- 原理介绍
- 实现一个拦截器类中维护一个数组,添加拦截器方法
use
, 移除拦截器方法eject
, 遍历拦截器方法forEach
- 利用数组
unshift
,push
方法,添加请求拦截器和响应拦截器 - 利用
Promise.then
链式调用添加的拦截器
- 实现一个拦截器类中维护一个数组,添加拦截器方法
如果大家有了解过 Koa
的中间件原理,可能会发现很相似
转换请求和响应数据
-
关键代码
-
原理介绍
- 默认配置中内置默认
transformRequest
,transformResponse
方法,处理常见情况 - 编写
transformData
方法,遍历多个转换器,处理数据
- 默认配置中内置默认
function transformData(data, headers, fns) { /*eslint no-param-reassign:0*/ utils.forEach(fns, function transform(fn) { data = fn(data, headers); }); return data; }; 复制代码
-
dispatchRequest
请求前,调用transformData
调用所有的请求转化器处理请求数据 - 请求完成后,调用
transformData
调用所有的响应转化器处理响应数据
取消请求
-
关键代码
-
原理介绍
- 创建一个
CancelToken
构造函数接受一个executor
函数,内部实例化一个pending
状态的Promise
对象,然后用一个resolvePromise
变量指向resolve
函数。 - 接着执行 executor 函数,传入一个
cancel
函数,在cancel
函数内部,会调用resolvePromise
把Promise
对象从pending
状态变为resolved
状态。 - 在
request
请求中的resolvePromise.then
被执行
- 创建一个
客户端支持防范 XSRF
- XSRF介绍
-
防范方法
- 验证请求
referer
, 但由于referer
也可以伪造,作用有限 - 服务器端生成
token
,并通过set-cookie
的方式种到客户端,然后客户端发送请求的时候,从cookie
中对应的字段读取出token
,然后添加到请求headers
中。由于这个token
比较难伪造,所以就能区分这个请求是否是用户正常发起的。
- 验证请求
-
关键代码
-
原理介绍
- 首先判断如果是配置
withCredentials
为true
或者是同域请求,我们才会请求headers
添加xsrf
相关的字段。 - 如果判断成功,尝试从
cookie
中读取xsrf
的token
值。 - 如果能读到,则把它添加到请求
headers
的xsrf
相关字段中。
- 首先判断如果是配置
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。