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