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}
    }
    })
    }

相关推荐
董世昌4112 小时前
如何声明一个类?类如何继承?
java·开发语言·前端
2501_9419820512 小时前
企业微信 API 外部群主动推送技术解析
前端·chrome
小鸡脚来咯12 小时前
后端开发vue速成
开发语言·前端·javascript
马达加斯加D12 小时前
Web系统设计 --- HTTP + GraphQL
前端·http·graphql
lifewange20 小时前
UI自动化页面元素定位有几种方式
前端·ui·自动化
牛奶21 小时前
2026 春涧·前端走向全栈
前端·人工智能·全栈
Piper蛋窝21 小时前
AI 有你想不到,也它有做不到 | 2025 年深度使用 Cursor/Trae/CodeX 所得十条经验
前端·后端·代码规范
LYFlied21 小时前
WebAssembly为何能实现极致性能:从设计原理到执行优势
前端·wasm·跨端
释怀不想释怀1 天前
vue布局,动态路由
前端·html
桜吹雪1 天前
Vue 基础:状态管理入门
前端·vue.js