vue项目中token延续,封装在axios中

import axios from 'axios'
import qs from 'qs'
import { setToken, removeToken } from '@/common/auth'
import { loadFromLocal, clearFormLocal, saveToLocal } from '@/common/local-storage'
import { refreshtoken } from '@/utils/index'
import router from '../router'
import context from '../main'

// axios.defaults.timeout = 8000 // 响应时间
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' // 配置请求头
axios.defaults.baseURL = '' // 配置接口地址

/* 是否正在刷新的标志 */
window.isRefreshing = false
/* 存储请求的数组 */
let refreshSubscribers = []

/* 将所有的请求都push到数组中,其实数组是[function(token){}, function(token){},...] */
function subscribeTokenRefresh(cb) {
  refreshSubscribers.push(cb)
}
/* 数组中的请求得到新的token之后自执行,用新的token去请求数据 */
function onRefreshed(token) {
  refreshSubscribers.map(cb => cb(token))
}

function isAccessTokenExpired() {
  let mills = new Date().getTime() - loadFromLocal('loginTime')
  // refreshToken expire in two days
  let isRefreshExpire = mills > 2 * 24 * 3600000
  // let isRefreshExpire = mills > 36000
  if (isRefreshExpire) {
    removeToken()
    clearFormLocal()
    router.push({ path: '/login' })
    return false
  }
  // token expire in less then 5 minutes
  let isTokenExpire = mills > (loadFromLocal('expire') - 300) * 1000
  return isTokenExpire
}

// POST传参序列化(添加请求拦截器)
axios.interceptors.request.use((config) => {
  // 在发送请求之前做某件事
  if (config.method === 'post') {
    config.data = qs.stringify(config.data)
  }
  /* 请求头添加token信息 */
  config.headers['token'] = loadFromLocal('token')

  /* 判断token是否即将过期* /
  /* `/sec/refreshToken`是刷新token的接口,只有当token将要过期且不是请求刷新token的接口才会进入 */
  if(isAccessTokenExpired() && config.url !== '/sec/refreshToken') {
    /* 首先所有的请求来了,我们要先判断当前是否正在刷新,如果不是,将刷新的标志置为true并请求刷新token;如果是,将请求存储到数组中 */
    if(!window.isRefreshing) {
      window.isRefreshing = true
      refreshtoken().then(res => { // refreshtoken为获取token的方法,包括window.isRefreshing = false
        if (res.code === 0) {
          /* 将刷新的token替代老的token */
          config.headers['token'] = res.data.token
          /* 更新内存的auth */
          setToken(res.data.token)
          saveToLocal('refreshToken', res.data.refreshToken)
          saveToLocal('token', res.data.token)
          saveToLocal('expire', res.data.expire)
          saveToLocal('loginTime', new Date().getTime())
          /* 执行数组里的请求,重新发起被挂起的请求 */
          onRefreshed(res.data.token)
          window.isRefreshing = false
        } else {
          removeToken()
          clearFormLocal()
          router.push({path: '/login'})
        }
      })
    }
    let retry = new Promise((resolve, reject) => {
      /* (token) => {...}这个函数就是cb */
      subscribeTokenRefresh((token) => {
        config.headers['token'] = token
          /* 将请求挂起 */
        resolve(config)
      })
    })
    return retry
  }else {
    return config
  }
}, (error) => {
  console.log('错误的传参')
  return Promise.reject(error)
})

// 返回状态判断(添加响应拦截器)
axios.interceptors.response.use((res) => {
  // 对响应数据做些事
  if (!res.data.success) {
    return Promise.resolve(res)
  }
  return res
}, (error) => {
  console.log('网络异常')
  context.$message.warning('当前网络状态差,请刷新后重试')
  return Promise.reject(error)
})

// 返回一个Promise(发送post请求)
export function fetchPost(url, params) {
  return new Promise((resolve, reject) => {
    axios.post(url, params)
      .then(response => {
        resolve(response.data)
      }, err => {
        reject(err)
      })
      .catch((error) => {
        reject(error)
      })
  })
}
// 返回一个Promise(发送get请求)
export function fetchGet(url, param) {
  return new Promise((resolve, reject) => {
    axios.get(url, { params: param })
      .then(response => {
        resolve(response.data)
      }, err => {
        reject(err)
      })
      .catch((error) => {
        reject(error)
      })
  })
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值