vue下axios拦截器token刷新机制的实例代码


Posted in Javascript onJanuary 17, 2020

//创建http.js文件,以下是具体代码:

//引入安装的axios插件
import axios from 'axios'
import router from '@/router';
import Vue from 'vue'
const qs = require("qs");
let _this = new Vue();
let isLock = false;
let refreshSubscribers = [];
//判断token是否过期
function isTokenExpired(token) {
 let expires_time = JSON.parse(token).expires_time;
 let curentTime = new Date().getTime();
 if (curentTime >= expires_time) {
  return true;
 } else {
  return false;
 }
}
//获取Token对象
function getToken() {
 return localStorage.getItem("token");
}
//push所有请求到数组中
function subscribeTokenRefresh(cb) {
 refreshSubscribers.push(cb)
}

//刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)
function onRrefreshed(token) {
 refreshSubscribers.map(cb => cb(token))
}
//刷新token
function refreshToken(config, token, resolve, reject) {
 let data = { refresh_token: JSON.parse(token).refresh_token };
 axios({
  method: "post",
  url: "xxxxxx/refreshToken",//刷新token的接口
  headers: {
   "Content-Type": "application/x-www-form-urlencoded",
   "Authorization": "Basic b3JkZXItc2VydmVyOjEyMzQ1Ng=="
  },
  data: qs.stringify(data)
 }).then(res => {
  isLock = false;//释放锁
  if (res.data.code === 101) {
   _this.$message.error('登录状态已失效,请重新登录。');
   localStorage.removeItem("token");
   router.push({
    path: "/login"
   });
   return;
  }

  let expires_time = new Date().getTime() + parseInt(res.data.data.expires_in * 0.8) * 1000;
  let token = JSON.parse(localStorage.getItem("token"));
  token.expires_time = expires_time;
  token.access_token = res.data.data.access_token;
  localStorage.setItem("token", JSON.stringify(token));

  config.headers.Authorization = 'Bearer ' + res.data.data.access_token;
  resolve(config);
  //执行数组里的函数,重新发起被挂起的请求
  onRrefreshed(res.data.data.access_token)
  //清空数组中保存的请求
  refreshSubscribers = []
 }).catch(err => {
  return err;
 });
}

function request(newOptions, resolve, reject) {
 axios({
  method: newOptions.method,
  url: newOptions.url,
  data: newOptions.type == "form" ? qs.stringify(newOptions.data) : newOptions.data,
  headers: newOptions.headers
 }).then(res => {
  if (res.status == 200) {
   //这里我们只需要获取返回的data中的数据即可
   resolve(res.data);
  } else {
   reject(res.data);
  }
 }).catch(err => {
  reject(err);
  _this.$message.error('服务异常!');
 })
}

axios.interceptors.request.use(
 config => {
  let token = getToken();
  if (token) {
   //判断token是否过期,如果过期请求刷新token
   if (isTokenExpired(token)) {
    //判断当前是否正在请求刷新token
    if (!isLock) {
     isLock = true;//isLock设置true,锁住防止死循环。
     //使用Promise等待刷新完成返回配置信息
     let refresh = new Promise((resolve, reject) => {
      refreshToken(config, token, resolve, reject);
     })
     return refresh;

    } else {
     //判断当前url是否是刷新token的请求地址,如果是直接下一步。
     if (config.url.indexOf('/logined/refreshToken') === -1) {
      //把请求(token)=>{....}都push到一个数组中
      let retry = new Promise((resolve, reject) => {
       //(token) => {...}这个函数就是回调函数
       subscribeTokenRefresh((token) => {
        config.headers.Authorization = 'Bearer ' + token
        //将请求挂起
        resolve(config)
       })
      })
      return retry

     } else {
      return config;
     }
    }

   } else {
    return config;
   }

  } else {
   return config;
  }
 }, error => {
  return Promise.reject(error);
 });
const http = options => {
 return new Promise((resolve, reject) => {
  const defaultOptions = {
   type: "json"
  };
  const newOptions = {
   ...defaultOptions,
   ...options
  };
  //headers默认传递json格式数据,这里也可以设置token,每次调用都会携带
if (localStorage.getItem("token")) {
    newOptions.headers = {
     // 'Authorization': 'Basic b3JkZXItc2VydmVyOjEyMzQ1Ng==',
     'content-Type': newOptions.type == 'form' ? 'application/x-www-form-urlencoded;charset=UTF-8' : 'application/json;charset=UTF-8',
     'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem("token")).access_token,
     ...newOptions.headers
    };
   } else {
    newOptions.headers = {
     'content-Type': newOptions.type == 'form' ? 'application/x-www-form-urlencoded;charset=UTF-8' : 'application/json;charset=UTF-8',
     ...newOptions.headers
    };
   }
  request(newOptions, resolve, reject);
 })
};

//设置请求超时
axios.defaults.timeout = 30000
export default http

//在main.js下面挂载 http.js文件
import http from '@/utils/http.js';
Vue.prototype.http = http;

//登录保存token信息接口

this.http({
      method: "post",
      url: "/xxxxx/user",
      type: "form",
      headers: { Authorization:"Basicb3JkZXItc2VydmVyOjEyMzQ1Ng==" },
      data: {}
     }).then(function(res) {
        let expires_time =
         new Date().getTime() +
         parseInt(res.data.token.expires_in * 0.8) * 1000;
         let token = res.data.token;
         token.expires_time = expires_time;
        localStorage.setItem("token", JSON.stringify(token));
    
      }).catch(function(err) {
       console.log(err);
      });        

//退出清空token
this.http({
    method: "get",
    url: "/xxxxx/logout",
    data: {}
   }).then(function(res) {
 localStorage.removeItem("token");
  }).catch(function(err) {
     console.log(err);
    });

总结

以上所述是小编给大家介绍的vue下axios拦截器token刷新机制的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
飞鱼(shqlsl) javascript作品集
Dec 16 Javascript
用prototype实现的简单小巧的多级联动菜单
Mar 24 Javascript
分享14个很酷的jQuery导航菜单插件
Apr 25 Javascript
javascript实现倒计时并弹窗提示特效
Jun 05 Javascript
js实现iframe框架取值的方法(兼容IE,firefox,chrome等)
Nov 26 Javascript
jQuery日程管理控件glDatePicker用法详解
Mar 29 jQuery
微信小程序授权获取用户详细信息openid的实例详解
Sep 20 Javascript
vue学习教程之带你一步步详细解析vue-cli
Dec 26 Javascript
微信小程序实现Session功能及无法获取session问题的解决方法
May 07 Javascript
详解vue 在移动端体验上的优化解决方案
May 20 Javascript
微信小程序实现组件顶端固定或底端固定效果(不随滚动而滚动)
Apr 09 Javascript
vue监听浏览器原生返回按钮,进行路由转跳操作
Sep 09 Javascript
js布局实现单选按钮控件
Jan 17 #Javascript
vue 查看dist文件里的结构(多种方式)
Jan 17 #Javascript
JavaScript数组去重实现方法小结
Jan 17 #Javascript
JS面向对象之多选框实现
Jan 17 #Javascript
JavaScript基于面向对象实现的无缝滚动轮播示例
Jan 17 #Javascript
JS面向对象之单选框实现
Jan 17 #Javascript
原生JavaScript实现的无缝滚动功能详解
Jan 17 #Javascript
You might like
PHP SEO优化之URL优化方法
2011/04/21 PHP
PHP APP微信提现接口代码
2018/09/30 PHP
WebGame《逆转裁判》完整版 代码下载(1月24日更新)
2007/01/29 Javascript
一些易混淆且不常用的属性,希望有用
2007/01/29 Javascript
IE6下javasc#ipt:void(0) 无效的解决方法
2013/12/23 Javascript
JavaScript实现基于Cookie的存储类实例
2015/04/10 Javascript
移动手机APP手指滑动切换图片特效附源码下载
2015/11/30 Javascript
简单的jQuery拖拽排序效果的实现(增强动态)
2017/02/09 Javascript
vue.js父组件使用外部对象的方法示例
2017/04/25 Javascript
jquery获取链接地址和跳转详解(推荐)
2017/08/15 jQuery
通过fastclick源码分析彻底解决tap“点透”
2017/12/24 Javascript
一文快速详解前端框架 Vue 最强大的功能
2019/05/21 Javascript
JavaScript实现简易计算器小功能
2020/10/22 Javascript
python 布尔操作实现代码
2013/03/23 Python
详解Django框架中的视图级缓存
2015/07/23 Python
Python实现Smtplib发送带有各种附件的邮件实例
2017/06/05 Python
python实现画圆功能
2018/01/25 Python
python中的decorator的作用详解
2018/07/26 Python
[原创]Python入门教程2. 字符串基本操作【运算、格式化输出、常用函数】
2018/10/29 Python
Python中的元组介绍
2019/01/28 Python
python+pyqt5实现图片批量缩放工具
2019/03/18 Python
TensorFlow获取加载模型中的全部张量名称代码
2020/02/11 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
基于HTML5 WebGL的3D机房的示例
2018/03/16 HTML / CSS
俄罗斯电子产品在线商店:UltraTrade
2020/01/30 全球购物
Tomcat中怎么使用log4j输出所有的log
2016/07/07 面试题
工程现场管理求职自荐信
2013/10/02 职场文书
数据员岗位职责
2013/11/19 职场文书
车工岗位职责
2013/11/26 职场文书
主管会计岗位责任制
2014/02/10 职场文书
软件项目实施计划书
2014/05/02 职场文书
母亲节演讲稿
2014/05/27 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
党的群众路线查摆剖析材料
2014/10/10 职场文书
2014年社区矫正工作总结
2014/11/18 职场文书
vue elementUI批量上传文件
2022/04/26 Vue.js