Axios的拦截器原理以及请求等待重发的实现

您所在的位置:网站首页 axios拦截器设置请求头 Axios的拦截器原理以及请求等待重发的实现

Axios的拦截器原理以及请求等待重发的实现

#Axios的拦截器原理以及请求等待重发的实现| 来源: 网络整理| 查看: 265

  Vue项目越做越多,Axios一直作为请求发送的基础工程,这里就深究一下Axios的拦截器相关的一些逻辑和对应一个比较恶心的场景。

  Axios GitHub

  回顾下Promise

  Promise的基础知识不做多介绍可以参考两个文章

  《ECMAScript 6 入门》:Promise 对象

  ES6 Promise的resolved深入理解 这个是我看到的对于Promise状态解释比较清晰的一个文章

  Promise的状态

  Promise状态一旦改变就不能再变,一直保持此状态

  Promise可以被其他Promise锁定----这个很重要,跟后面的要说到的Axios的请求阻塞等待有关系

  一个重要的Demo

  输出如下结果

  简单解释下上面的结果

  Promise.resolve创建一个Promise对象,依赖于inner的Promise的resolve结果

  内部的new Promise().then()创建了一个Promise,new Promise()resolve的结果是123,then()将结果改为1234,打印string 123,然后返回'1234'这个作为外层的resolve结果

  外层中第一个then()返回了一个Promise返回Randy1234作为resolve结果

  外层中第二个then()接收到前一个的返回值,然后打印string Randy1234

  人话描述下这里用到的几个知识点

  Promise.resolve(data)等于new Promise(resolve={resolve(data)})

  Promise A可以使用另一个Promise B的resolve值作为自己的resolve值进入A的调用链

  then()可以对处理结果进行修改

  Axios

  接下来开始整体,说说Axios。Axios是基于Promise机制实现的异步的链式请求框架。体积小,源码易懂。非常适合做基础的请求库。

  Axios结构

  代码结构

  axios.js:入口文件,将Axios实例的request函数绑定为入口函数,axios.create其实返回的是一个function,就是Axios实例的Axios.prototype.request

  lib/Axios.js:真正的Axios的实例,用于拼接拦截器的调用链,关键代码如下:

  lib/InterceptorManager.js:拦截器管理,是一个对[]的封装

  lib/dispatchRequest.js:发送请求的Promise,完成发送请求的逻辑。注意看Axios.js中的var chain = [dispatchRequest, undefined];

  adapter/*:适配器,这里的代码保证了Axios在ssr模式下和浏览器环境中区分环境实现请求返送的逻辑。里面存放了两个定义好的适配器,可以参照README.md中的描述自定义适配器

  拦截器模型

  Axios拦截器示意图.png

  request和response的拦截器都可以有多对,其中每一个点都会挂在一个then()的调用上,promise.then(chain.shift(), chain.shift());

  使用场景:应对OAuth中refresh_token换access_token时其他请求需等待的问题

  根据场景来看,我们需要有一下几个能力

  Request拦截器中任意的请求(比如请求A)进入之后,如果主动检测到了access_token的超时,那么停止当前请求A,开启refresh_token的请求,当成功之后再执行A请求

  当请求已发送,服务端识别到了token失效,Response拦截器中的处理跟Request拦截器要做的事一样

  当有进行中的refresh_token请求时,此请求需要等待这个进行中的refresh_token的请求成功之后再进行发送

  那我们一个一个来处理

  当请求进入拦截器,主动发现需要refresh_token时(比如access_token有效期临近)需要将请求放置在refresh_token成功之后

  处理方式可以采用在then()调用拦截器的方法时返回一个Promise,然后在Promise中等待refresh_token的请求成功之后再进行当前进入的请求的发送

  上面的代码只是一个简单的示意,实际处理中要注意以下几点,

  刷新token之后config_param要处理新Token的拼装;

  请求拦截器中要能识别出是否是refresh_token的请求;

  能识别出是否正在进行refresh_token,并能正确处理其他进入的请求,这个后面会讲到

  处理之后调用链会变成这样

  请求拦截器中加入Promise

  当请求已发送,服务端识别到了Token失效时(这个情况比较多,服务器时间与本地有间隙;Token不支持多点登陆等等),需要先refresh_token,然后重发请求

  可以采用与Request拦截器相似的处理,在拦截器中同样开启refresh_token,成功之后重新创建已经失败的请求,执行完请求之后将重新创建的请求获取到的返回值resolve给response的返回值

  处理之后调用链会变成这样

  响应拦截器中加入Promise和二次请求

  对于在refresh_token时其他请求的进入需要安排这个请求动作,让请求发生在refresh_token之后进行

  - 解决思路如下,在全局的状态中记录是否正在刷新请求,并且保存refresh_token的Promise。当遇到请求之后新创建一个Promise交给拦截器,在新创建的Promise中用then()等待refresh_token。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3