ts 联合react 实现ajax的封装,refreshtoken的功能

react ts混合双打,实现ajax的封装,以及401的特殊处理

复制代码
import axios from 'axios'
import {
  AMDIN_EXPIRES_KEY,
  AMDIN_KEY,
  AMDIN_REFRESH_EXPIRES_KEY,
  AMDIN_REFRESH_KEY,
  COMMID_KEY,
  getToken,
  removeToken
} from '../utils/user-token'
import { showMessage } from '../utils/feedback'
import { fetchGetRefreshInfo } from './user'
import { setUserToken } from '../utils/public'
import router from '../router'

// 失败的fetch 集合
let isRefreshing = false
let failedQueue: any[] = []

// 创建一个axios实例
const instance = axios.create()

// 添加请求拦截器
instance.interceptors.request.use(
  (config: any) => {
    // 在发送请求之前做些什么
    const token = getToken(AMDIN_KEY)
    // if (token) {
    // config.headers.Authorization = `Bearer ${token}` // 将token设置到请求头中

    config.headers = {
      Authorization: `Bearer ${token}`,
      ...config.headers
    }
    // }
    return config
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 添加响应拦截器
instance.interceptors.response.use(
  async (res) => {
    const resData = (res.data || {}) as ResType
    // console.log('response - resData: ', resData)
    const { code, msg = '系统正在升级,稍后再试' } = resData

    if ((code) === 200) {
      return Promise.resolve(resData as any)
    } else {
      await showMessage(msg).then(() => {
        return Promise.reject(resData)
      })
    }
  },
  async (error) => {
    // 对响应错误做点什么
    // if (error.response && error.response.status === 401) {
    //   // 判断是否为401
    //   const refreshToken = getToken(AMDIN_REFRESH_KEY)
    //   if (refreshToken) {
    //     try {
    //       // 使用refreshToken请求新的token
    //       const res = await fetchGetRefreshInfo()
    //       // 将新的token保存到localStorage
    //       setUserToken(res.Data.token)
    //       // 用新的token重新发送失败的请求
    //       const config = error.config
    //       config.headers.Authorization = `Bearer ${getToken(AMDIN_KEY)}`
    //       return instance(config)
    //     } catch (err) {
    //       console.error('刷新token失败', err)
    //       // 刷新token失败,跳转到登录页等处理
    //       router.navigate(`/login?commId=${getToken(COMMID_KEY)}`, {
    //         replace: true
    //       })
    //     }
    //   }
    // }

    if (error.response && error.response.status === 401) {
      // 特殊处理 当RefreshToken 的接口401时候,及RefreshToken token的也过期了
      // 如果不处理,将会死循环
      if (error.response.config.url.indexOf('RefreshToken') > -1) {
        // 刷新token失败,跳转到登录页等处理
        removeToken(AMDIN_KEY)
        removeToken(AMDIN_EXPIRES_KEY)
        removeToken(AMDIN_REFRESH_EXPIRES_KEY)
        removeToken(AMDIN_REFRESH_KEY)
        router.navigate(`/login?commId=${getToken(COMMID_KEY)}`, {
          replace: true
        })
        return
      }

      const originalRequest = error.config
      if (!isRefreshing) {
        isRefreshing = true

        await fetchGetRefreshInfo()
          .then((res) => {
            // 将新的token保存到localStorage
            setUserToken(res.Data.token)

            isRefreshing = false
            const newToken = getToken(AMDIN_KEY)
            processQueue(null, newToken)
            originalRequest.headers['Authorization'] = 'Bearer ' + newToken
            return instance(originalRequest)
          })
          .catch((err) => {
            processQueue(err, null)

            return Promise.reject(err)
          })
      } else {
        return new Promise(function (resolve, reject) {
          failedQueue.push({ resolve, reject })
        })
          .then((token) => {
            originalRequest.headers['Authorization'] = 'Bearer ' + token
            return instance(originalRequest)
          })
          .catch((err) => {
            return Promise.reject(err)
          })
      }
    }
    return Promise.reject(error)
  }
)

const processQueue = (error: any, token: string | null = null) => {
  failedQueue.forEach((prom) => {
    if (error) {
      prom.reject(error)
    } else {
      prom.resolve(token)
    }
  })

  failedQueue = []
}

export default instance

export type ResType = {
  code?: number
  data?: ResDataType
  msg?: string
}

export type ResDataType = {
  [key: string]: any
}
  • service.ts

    // 刷新token
    export async function fetchGetRefreshInfo(): Promise<ResDataType> {
    const url = ${REACT_APP_URL}/XXXXXXXXXXXXXXXXX/RefreshToken
    return axios({
    url,
    method: 'post',
    headers: {
    Authorization: Bearer ${refreshToken}
    }
    })
    }

相关推荐
weixin-a153003083162 分钟前
【playwright篇】教程(十七)[html元素知识]
java·前端·html
ai小鬼头29 分钟前
AIStarter最新版怎么卸载AI项目?一键删除操作指南(附路径设置技巧)
前端·后端·github
wen's36 分钟前
React Native 0.79.4 中 [RCTView setColor:] 崩溃问题完整解决方案
javascript·react native·react.js
一只叫煤球的猫1 小时前
普通程序员,从开发到管理岗,为什么我越升职越痛苦?
前端·后端·全栈
vvilkim1 小时前
Electron 自动更新机制详解:实现无缝应用升级
前端·javascript·electron
vvilkim1 小时前
Electron 应用中的内容安全策略 (CSP) 全面指南
前端·javascript·electron
aha-凯心1 小时前
vben 之 axios 封装
前端·javascript·学习
遗憾随她而去.2 小时前
uniapp 中使用路由导航守卫,进行登录鉴权
前端·uni-app
xjt_09012 小时前
浅析Web存储系统
前端
foxhuli2293 小时前
禁止ifrmare标签上的文件,实现自动下载功能,并且隐藏工具栏
前端