vue3基于axios配置请求拦截器响应拦截器以及无感刷新token的实现

一、下载并引入 axios

npm i axios
  • 创建request=>index.js
import axios from 'axios'

二、引入 element-plus 消息提示

import { ElMessage, ElMessageBox } from 'element-plus'

三、配置基础地址

可参考历史文章vue3项目打包上线后,如何配置api接口地址,省去更换api再次打包

//生产环境下读取 public=>static=>config.js 中的 api 变量(用于上线后动态配置接口地址)
const BASE_URL =
process.env.NODE_ENV === 'development'
? process.env.VUE_APP_API_URL
: window.webConfig.webApiBaseUrl

四、创建 axios 实例

const request = axios.create({
baseURL: BASE_URL,
timeout: 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})

五、配置请求拦截器

request.interceptors.request.use((config) => {
config.headers = config.headers || {}, //设置请求头
config.headers['Token'] = localStorage.getItem('Token') || ''
config.headers['Code'] = localStorage.getItem('Code') || ''
return config
})

六、定义是否刷新 token 的变量以及存储请求队列的数组

//是否刷新 token
let isRefreshing = false
//请求队列
let requestList = [] as any[]

七、配置响应拦截器以及实现无感刷新 token

request.interceptors.response.use(
async (res: any) => {
// 路由
const Code: number = res.data.Code || 0

    const config = res.config
    //处理token过期==>更新token
    if (Code == -1) {
      if (!isRefreshing) {
        isRefreshing = true
        //id (用于获取token)
        const appid = process.env.VUE_APP_APPID.replace(/"/g, '')
        //密钥 (用于获取token)
        const secret = process.env.VUE_APP_SECRET.replace(/"/g, '')
        //请求获取token接口
        return (
          request({
            url: `outside/getAccessToken?appid=${appid}&secret=${secret}`,
            method: 'GET',
          })
            .then((res) => {
              //存token缓存
              localStorage.setItem('Token', res.data.data)
              config.headers.token = res.data.data
              let response = request(config)
              // 刷新成功后将请求队列里的请求依次执行
              requestList.forEach((cb) => cb())
              requestList = [] // 执行完毕后将请求队列置空
              return response
            })
            .finally(() => {
              isRefreshing = false
            })
        )
      } else {
        return new Promise((resolve) => {
          requestList.push(() => {
            config.headers.token = localStorage.getItem('Token')
            let response = request(config)
            resolve(response)
          })
        })
      }
    } else if (Code == 0) {
      //处理code过期==>退出登录 (tokenExpired是防止code过期后,下方提示消息显示多次)
      let tokenExpired = localStorage.getItem('tokenExpired')
      if (tokenExpired == 'false' || !tokenExpired) {
        localStorage.setItem('tokenExpired', 'true')
        ElMessageBox.confirm('登录已过期,请重新登录!', '提示', {
          confirmButtonText: '确定',
          showClose: false,
          showCancelButton: false,
          closeOnClickModal: false,
          type: 'warning',
        }).then(() => {

          //清除缓存
          localStorage.removeItem('Token')
          localStorage.removeItem('UserGlobalStore')
          localStorage.removeItem('Code')
          // 重新加载页面(清除路由缓存)
          window.location.reload()
          // 在页面加载完成后跳转到登录页面
          window.onload = function () {
            window.location.href = '/login'
          }
        })
      } else {
        //清除缓存
        localStorage.removeItem('Token')
        localStorage.removeItem('UserGlobalStore')
        localStorage.removeItem('Code')
        // 重新加载页面(清除路由缓存)
        window.location.reload()
        // 在页面加载完成后跳转到登录页面
        window.onload = function () {
          window.location.href = '/login'
        }
      }
    }  else {
      return Promise.resolve(res)
    }

},
(err) => {
//接口出错
ElMessage.error(err.message)
return Promise.reject(err)
}
)

八、导出axios

export default request

九、封装接口请求

import request from '@/request/index'

export function getYourApi(data: Object) {
return request({
url: 'yourApi',
method: 'GET',
params: data,
})
}

十、使用接口请求

import { getYourApi } from '@/api/yourApi'
getYourApi({}).then((res) => {
...
}).catch((err) => {
})

十一、完整代码

  • 第一步到第八步代码
import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'

//生产环境下读取 public=>static=>config.js 中的 api 变量(用于上线后动态配置接口地址)
const BASE_URL =
process.env.NODE_ENV === 'development'
? process.env.VUE_APP_API_URL
: window.webConfig.webApiBaseUrl

const request = axios.create({
baseURL: BASE_URL,
timeout: 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})

request.interceptors.request.use((config) => {
config.headers = config.headers || {}, //设置请求头
config.headers['Token'] = localStorage.getItem('Token') || ''
config.headers['Code'] = localStorage.getItem('Code') || ''
return config
})

//是否刷新 token
let isRefreshing = false
//请求队列
let requestList = [] as any[]

request.interceptors.response.use(
async (res: any) => {
// 路由
const Code: number = res.data.Code || 0

    const config = res.config
    //处理token过期==>更新token
    if (Code == -1) {
      if (!isRefreshing) {
        isRefreshing = true
        //id (用于获取token)
        const appid = process.env.VUE_APP_APPID.replace(/"/g, '')
        //密钥 (用于获取token)
        const secret = process.env.VUE_APP_SECRET.replace(/"/g, '')
        //请求获取token接口
        return (
          request({
            url: `outside/getAccessToken?appid=${appid}&secret=${secret}`,
            method: 'GET',
          })
            .then((res) => {
              //存token缓存
              localStorage.setItem('Token', res.data.data)
              config.headers.token = res.data.data
              let response = request(config)
              // 刷新成功后将请求队列里的请求依次执行
              requestList.forEach((cb) => cb())
              requestList = [] // 执行完毕后将请求队列置空
              return response
            })
            .finally(() => {
              isRefreshing = false
            })
        )
      } else {
        return new Promise((resolve) => {
          requestList.push(() => {
            config.headers.token = localStorage.getItem('Token')
            let response = request(config)
            resolve(response)
          })
        })
      }
    } else if (Code == 0) {
      //处理code过期==>退出登录 (tokenExpired是防止code过期后,下方提示消息显示多次)
      let tokenExpired = localStorage.getItem('tokenExpired')
      if (tokenExpired == 'false' || !tokenExpired) {
        localStorage.setItem('tokenExpired', 'true')
        ElMessageBox.confirm('登录已过期,请重新登录!', '提示', {
          confirmButtonText: '确定',
          showClose: false,
          showCancelButton: false,
          closeOnClickModal: false,
          type: 'warning',
        }).then(() => {

          //清除缓存
          localStorage.removeItem('Token')
          localStorage.removeItem('UserGlobalStore')
          localStorage.removeItem('Code')
          // 重新加载页面(清除路由缓存)
          window.location.reload()
          // 在页面加载完成后跳转到登录页面
          window.onload = function () {
            window.location.href = '/login'
          }
        })
      } else {
        //清除缓存
        localStorage.removeItem('Token')
        localStorage.removeItem('UserGlobalStore')
        localStorage.removeItem('Code')
        // 重新加载页面(清除路由缓存)
        window.location.reload()
        // 在页面加载完成后跳转到登录页面
        window.onload = function () {
          window.location.href = '/login'
        }
      }
    }  else {
      return Promise.resolve(res)
    }

},
(err) => {
//接口出错
ElMessage.error(err.message)
return Promise.reject(err)
}
)

export default request
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gik99

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值