// 封装axios import { Toast } from 'antd-mobile' import axios, { AxiosError } from 'axios' import store from '@/store' import { getToken, setToken } from './storage' import { logout } from '@/store/actions/login' import history from './history' export const baseURL = '/api' // export const baseURL = 'geek.itheima.net' const instance = axios.create({ baseURL: baseURL + /v1_0/, timeout: 5000, })
// 这个实例专门用于刷新token // axios的写法:baseURL可以分开写 和url const instance2 = axios.create({ baseURL: baseURL + /v1_0/, timeout: 5000, })
// 添加请求拦截器
instance.interceptors.request.use(
function (config) {
const token = getToken()
if (token.token && config.headers) {
config.headers.Authorization = Bearer ${token.token}
}
return config
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 添加响应拦截器
instance.interceptors.response.use(
function (response) {
// 对响应数据做点什么
return response
},
async function (error: AxiosError<{ message: string }>) {
if (!error.response) {
// 由于网络繁忙导致的
Toast.show('网络繁忙,稍后再试')
return Promise.reject(error)
}
console.dir(error)
// 1. 判断是否401错误
if (error.response.status === 401) {
// 2. 是401错误 没有token token过期了
const token = getToken()
if (token.token && token.refresh_token) {
try {
// 3. 有token, token过期, 尝试去刷新token,注意需要使用原始的axios来刷新,
// 因为响应拦截器被添加了token,这里要发送的是refresh_token
const res = await instance2({
url: '/authorizations',
method: 'put',
headers: {
Authorization: Bearer ${token.refresh_token},
},
})
console.log(res)
// 4. 刷新token成功,将新的token保存到redux中
store.dispatch({
type: 'login/login',
payload: {
// 这里要根据后端返回的情况 refresh_token: token.refresh_token是用的上一次的,所以如果过期,那么15天以后还是需要重新登录
// 所以如果说后端可以给一个新的refreshtoken,就可以实现一直登录
token: res.data.data.token,
refresh_token: token.refresh_token,
},
})
setToken({
token: res.data.data.token,
refresh_token: token.refresh_token,
})
// 在登录那里,401了,拿到了token,返回空就会报错,所以要返回一个。因为Token已经没问题了,重新发送请求拿到用户信息
console.dir(error) //拿到所有信息
return instance(error.config) //所有的url method都在error.config
} catch {
// 刷新失败
// 1. 移除token
store.dispatch(logout())
// 2. 跳转到登录页
// window.location.href = '/login'
history.replace('/login', { from: history.location.pathname })
Toast.show('登录信息失效')
return Promise.reject(error)
}
} else {
// 401错误是没有token导致的
// console.log('跳转到登录页')
// window.location.href = '/login'
history.replace('/login', { from: history.location.pathname })
}
}
Toast.show(error.response.data.message)
return Promise.reject(error)
} )
export default instance