axios 缓存 Token无痛刷新

傷城~ 2022-09-15 05:44 288阅读 0赞

参考链接

  1. /* * @Author: zhang gen yuan * @Date: 2021-10-09 17:51:00 * @Descripttion: */
  2. import axios from 'axios'
  3. // 数据存储
  4. export const cache = {
  5. data: { },
  6. set (key, data, bol = false) {
  7. if (bol) {
  8. localStorage.setItem(key, JSON.stringify(data))
  9. } else {
  10. this.data[key] = data
  11. }
  12. },
  13. get (key, bol = false) {
  14. if (bol) {
  15. return JSON.parse(localStorage.getItem(key))
  16. } else {
  17. return this.data[key]
  18. }
  19. },
  20. clear (key, bol = false) {
  21. if (bol) {
  22. localStorage.removeItem(key)
  23. } else {
  24. delete this.data[key]
  25. }
  26. }
  27. }
  28. // 建立唯一的key值
  29. function buildUrl (url, params = { }) {
  30. const sortedParams = Object.keys(params).sort().reduce((result, key) => {
  31. result[key] = params[key]
  32. return result
  33. }, { })
  34. url += `?${ JSON.stringify(sortedParams)}`
  35. return url
  36. }
  37. // 缓存,建议只给get加缓存
  38. export default (options = { }) => config => {
  39. const { url, method, params, data } = config
  40. const { local = false } = options
  41. // 建立索引
  42. let index
  43. if (method === 'get') {
  44. index = buildUrl(url, params)
  45. } else {
  46. index = buildUrl(url, data)
  47. }
  48. const indexData = index + '-data'
  49. let response = cache.get(indexData, local)
  50. let responsePromise = cache.get(index)
  51. if (response) {
  52. return Promise.resolve(JSON.parse(JSON.stringify(response))) // 对象是引用,为了防止污染数据源
  53. } else if (!responsePromise) {
  54. responsePromise = (async () => {
  55. try {
  56. const response = await axios.defaults.adapter(config)
  57. cache.set(indexData, response, local)
  58. return Promise.resolve(JSON.parse(JSON.stringify(response))) // 同时发送多次一样的请求,没办法防止污染数据源,只有业务中去实现
  59. } catch (reason) {
  60. cache.clear(index, local)
  61. cache.clear(indexData)
  62. return Promise.reject(reason)
  63. }
  64. })()
  65. // put the promise for the non-transformed response into cache as a placeholder
  66. cache.set(index, responsePromise)
  67. }
  68. return responsePromise
  69. }

使用

import axios from “axios”;
import cache from “./…/utils/axios”;

  1. axios.get("/api/blade-auth/oauth/captcha", {
  2. adapter: cache({
  3. local: false
  4. }),
  5. }).then(res=>{
  6. console.log(res)
  7. })
  8. import axios from 'axios'
  9. // 从localStorage中获取token
  10. function getLocalToken () {
  11. const token = window.localStorage.getItem('token')
  12. return token
  13. }
  14. // 给实例添加一个setToken方法,用于登录后将最新token动态添加到header,同时将token保存在localStorage中
  15. instance.setToken = (token) => {
  16. instance.defaults.headers['X-Token'] = token
  17. window.localStorage.setItem('token', token)
  18. }
  19. function refreshToken () {
  20. // instance是当前request.js中已创建的axios实例
  21. return instance.post('/refreshtoken').then(res => res.data)
  22. }
  23. // 创建一个axios实例
  24. const instance = axios.create({
  25. baseURL: '/api',
  26. timeout: 300000,
  27. headers: {
  28. 'Content-Type': 'application/json',
  29. 'X-Token': getLocalToken() // headers塞token
  30. }
  31. })
  32. // 是否正在刷新的标记
  33. let isRefreshing = false
  34. // 重试队列,每一项将是一个待执行的函数形式
  35. let requests = []
  36. instance.interceptors.response.use(response => {
  37. const { code } = response.data
  38. if (code === 1234) {
  39. const config = response.config
  40. if (!isRefreshing) {
  41. isRefreshing = true
  42. return refreshToken().then(res => {
  43. const { token } = res.data
  44. instance.setToken(token)
  45. config.headers['X-Token'] = token
  46. config.baseURL = ''
  47. // 已经刷新了token,将所有队列中的请求进行重试
  48. requests.forEach(cb => cb(token))
  49. requests = []
  50. return instance(config)
  51. }).catch(res => {
  52. console.error('refreshtoken error =>', res)
  53. window.location.href = '/'
  54. }).finally(() => {
  55. isRefreshing = false
  56. })
  57. } else {
  58. // 正在刷新token,将返回一个未执行resolve的promise
  59. return new Promise((resolve) => {
  60. // 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行
  61. requests.push((token) => {
  62. config.baseURL = ''
  63. config.headers['X-Token'] = token
  64. resolve(instance(config))
  65. })
  66. })
  67. }
  68. }
  69. return response
  70. }, error => {
  71. return Promise.reject(error)
  72. })
  73. export default instance

发表评论

表情:
评论列表 (有 0 条评论,288人围观)

还没有评论,来说两句吧...

相关阅读