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 {
  const url = `${REACT_APP_URL}/XXXXXXXXXXXXXXXXX/RefreshToken`
  return axios({
    url,
    method: 'post',
    headers: {
      Authorization: `Bearer ${refreshToken}`
    }
  })
}

你可能感兴趣的:(react.js,ajax,前端,reactjs)