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 相关文章推荐
表单的一些基本用法与技巧
Jul 15 Javascript
document.designMode的功能与使用方法介绍
Nov 22 Javascript
jQuery源码分析-03构造jQuery对象-工具函数
Nov 14 Javascript
兼容IE、firefox以及chrome的js获取时间(getFullYear)
Jul 04 Javascript
JS+CSS实现精美的二级导航效果代码
Sep 17 Javascript
深入浅析Bootstrap列表组组件
May 03 Javascript
js获取iframe中的window对象的实现方法
May 20 Javascript
JavaScript编写带旋转+线条干扰的验证码脚本实例
May 30 Javascript
深入理解angular2启动项目步骤
Jul 15 Javascript
JS实现合并json对象的方法
Oct 10 Javascript
解决jquery的ajax调取后端数据成功却渲染失败的问题
Aug 08 jQuery
vue中$refs, $emit, $on, $once, $off的使用详解
May 26 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实现绘制3D扇形统计图及图片缩放实例
2014/10/01 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
浅谈laravel数据库查询返回的数据形式
2019/10/21 PHP
为指定元素增加样式的js代码
2009/12/09 Javascript
JS对外部文件的加载及对IFRMAME的加载的实现,当加载完成后,指定指向方法(方法回调)
2011/07/04 Javascript
JavaScript网页定位详解
2014/01/13 Javascript
利用js实现禁止复制文本信息
2015/06/03 Javascript
JavaScript实现cookie的写入、读取、删除功能
2015/11/05 Javascript
一个用jquery写的判断div滚动条到底部的方法【推荐】
2016/04/29 Javascript
js字符串截取函数slice、substring和substr的比较
2016/05/17 Javascript
详解Node.Js如何处理post数据
2016/09/19 Javascript
详解AngularJS中的表单验证(推荐)
2016/11/17 Javascript
详解如何将angular-ui的图片轮播组件封装成一个指令
2017/05/09 Javascript
React组件之间的通信的实例代码
2017/06/27 Javascript
安装vue-cli报错 -4058 的解决方法
2017/10/19 Javascript
微信小程序如何调用json数据接口并解析
2019/06/29 Javascript
vue-element-admin 菜单标签失效的解决方式
2019/11/12 Javascript
详解Vue.js 响应接口
2020/07/04 Javascript
vue 计算属性和侦听器的使用小结
2021/01/25 Vue.js
Python的内存泄漏及gc模块的使用分析
2014/07/16 Python
为Python程序添加图形化界面的教程
2015/04/29 Python
Python中处理字符串之islower()方法的使用简介
2015/05/19 Python
python 实现数组list 添加、修改、删除的方法
2018/04/04 Python
Python基于dom操作xml数据的方法示例
2018/05/12 Python
Django框架ORM数据库操作实例详解
2019/11/07 Python
wxPython多个窗口的基本结构
2019/11/19 Python
使用 Python 读取电子表格中的数据实例详解
2020/04/17 Python
详解python中的lambda与sorted函数
2020/09/04 Python
python 如何在测试中使用 Mock
2021/03/01 Python
CSS3 实现弹幕的示例代码
2017/08/07 HTML / CSS
苏格兰销售女装、男装和童装的连锁店:M&Co
2018/03/16 全球购物
QA工程师岗位职责
2013/11/20 职场文书
廉洁教育学习材料
2014/05/19 职场文书
2014年人事行政工作总结
2014/12/03 职场文书
教师考核评语大全
2014/12/31 职场文书
闭幕词的写作格式与范文!
2019/06/24 职场文书