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 相关文章推荐
JQuery 操作select标签实现代码
May 14 Javascript
元素的内联事件处理函数的特殊作用域在各浏览器中存在差异
Jan 12 Javascript
JS去除数组重复值的五种不同方法
Sep 06 Javascript
Node.js中的process.nextTick使用实例
Jun 25 Javascript
Javascript中关于Array.filter()的妙用详解
Dec 04 Javascript
JavaScript 过滤关键字
Mar 20 Javascript
jQuery插件FusionCharts实现的MSBar2D图效果示例【附demo源码】
Mar 24 jQuery
JavaScript 基础表单验证示例(纯Js实现)
Jul 20 Javascript
详解如何使用PM2将Node.js的集群变得更加容易
Nov 15 Javascript
vue计算属性get和set用法示例
Feb 08 Javascript
html2canvas属性和使用方法以及如何使用html2canvas将HTML内容写入Canvas生成图片
Jan 12 Javascript
js判断在哪个浏览器打开项目的方法
Jan 21 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中使用ExcelFileParser处理excel获得数据(可作批量导入到数据库使用)
2010/08/21 PHP
php循环语句 for()与foreach()用法区别介绍
2012/09/05 PHP
解析:使用php mongodb扩展时 需要注意的事项
2013/06/18 PHP
php求两个目录的相对路径示例(php获取相对路径)
2014/03/27 PHP
PHP文件锁定写入实例解析
2014/07/14 PHP
[原创]smarty简单模板变量输出方法
2016/07/09 PHP
thinkPHP3.2.2框架行为扩展及demo示例
2018/06/19 PHP
IE和Mozilla的兼容性汇总event
2007/08/12 Javascript
JavaScript 操作键盘的Enter事件(键盘任何事件),兼容多浏览器
2010/10/11 Javascript
js实现双向链表互联网机顶盒实战应用实现
2011/10/28 Javascript
js保留两位小数使用toFixed实现
2013/07/29 Javascript
JS获得浏览器版本和操作系统版本的例子
2014/05/13 Javascript
JavaScript中innerHTML,innerText,outerHTML的用法及区别
2015/09/01 Javascript
jQuery中trigger()与bind()用法分析
2015/12/18 Javascript
CSS3 media queries结合jQuery实现响应式导航
2016/09/30 Javascript
详解RequireJS按需加载样式文件
2017/04/12 Javascript
JavaScript 中Date对象的格式化代码方法汇总
2017/09/06 Javascript
angular.extend方法的具体使用
2017/09/14 Javascript
浅谈webpack下的AOP式无侵入注入
2017/11/12 Javascript
理解 JavaScript EventEmitter
2018/03/29 Javascript
Vue数据双向绑定原理及简单实现方法
2018/05/18 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
2018/12/11 jQuery
vue实现文件上传读取及下载功能
2020/11/17 Javascript
vue实现分页加载效果
2019/12/24 Javascript
jQuery实现颜色打字机的完整代码
2020/03/19 jQuery
python的构建工具setup.py的方法使用示例
2017/10/23 Python
详解tensorflow实现迁移学习实例
2018/02/10 Python
python 日期排序的实例代码
2019/07/11 Python
PyCharm如何导入python项目的方法
2020/02/06 Python
Anaconda+vscode+pytorch环境搭建过程详解
2020/05/25 Python
浅谈python 类方法/静态方法
2020/09/18 Python
python lambda的使用详解
2021/02/26 Python
H5 canvas实现贪吃蛇小游戏
2017/07/28 HTML / CSS
HTML5中的拖放实现详解
2017/08/23 HTML / CSS
20年同学聚会感言
2014/02/03 职场文书
员工入职担保书范文
2014/04/01 职场文书