axios接口等待

126 阅读2分钟

 需求背景

现有两个项目,A、B ,A项目作为B的一个子系统使用。

现从B中进入A的入口逻辑是:

1. B点击进入到A,A项目检测当前系统是未登录的状态,接口返回错误code值与登录地址URL,web拿到URL进行跳转。

2. URL是B给A提供的免登录地址,跳转到这个地址B做个两件事情:a. 返回一个登录令牌token b. 重定向到A项目的地址并且附带着token

3. 再次进入到A项目中,axios的请求拦截器中获取下location.href地址中携带的token信息,并将其放在请求header中

4. 后台拿到请求的接口的header中的token去验证是否合法,合法则正常返回。

由第4步,引出了一个问题。

A项目一开始会去请求一个系统行的接口getSystem,token也是放在这个接口的header中的,但是首页一开始加载不止这一个接口,会同时请求四个接口。那么有接口在getSystem请求返回正确的信息之前就请求了,就又会验证失败,然后又到了第1步的跳转。这样就会一直循环页面的跳转,无法正常使用A

解决方式

利用axios拦截器,对接口进行等待,当getSystem接口返回信息之前,所有的请求接口都被拦截。当返回了信息,被拦截的接口再继续请求。

axiosManage.js:

import store from '@/store'

//全局标识符,标志着获取到了system信息,影响到每一个请求接口
let pendingFlag = ''; 

//getSystemInfo接口请求成功后,会将信息保存到Vuex中
const getSystemInfo = ()=>store.getters.systemInfo 

const waitSystemInfo =async function(){ 

 //gotInfo代表已经正常返回信息了,没必要拦截,直接返回成功的peomise
  if(pendingFlag==='gotInfo') return Promise.resolve()  return new Promise((resolve, reject) => {

   //轮询着去获取systemInfo信息,如果获取到了logFlag证明接口返回内容了
   //此时就清除定时器,直接返回resolve,成功的promise
   //如果没有获取到,什么都不处理,外层就是一个pending状态的promise
   //这里的pendingFlag比较重要,如果没有这个全局标志,那么无法影响到每一个被拦截的接口   let intervel= setInterval(() => {      let {logFlag}=getSystemInfo();      if(logFlag){         clearInterval(intervel)        pendingFlag='gotInfo';        resolve();      }    },500);   })}

export async function post (url, params) {

  if(url!=='/api/getSystemInfo'){ 

 //这里利用await的语法糖性质:等待promise的状态修改之后,才继续往下走,
 //如果方法返回一个pending状态的promise,那逻辑会一直在这里等待
 //一旦pendingFlag变为gotInfo,每一个拦截的请求接口都会在这里被放开,逻辑向下走      await waitSystemInfo ();  }  return new Promise((resolve, reject) => {    instance      .post(url, params, showLoading)      .then(        ...      )      .catch(err => {        reject(err.data)      })      .finally(err => {        ...      })  })}