accessToken过期后使用refreshToken调用刷新 token 接口去获取新的accessToken
class TokenManager {
constructor() {
this.promise = null
}
setToken(token) {
localStorage.setItem('accessToken', token)
}
getRefreshToken() {
return localStorage.getItem('refreshToken')
}
removeToken() {
localStorage.removeItem('accessToken')
localStorage.removeItem('refreshToken')
localStorage.removeItem('name')
}
async refreshAccessToken() {
const response = await fetch('/api/v3/Logon/getRefreshUserToker', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Refresh-Token': 'true',
},
body: JSON.stringify({
refreshToken: this.getRefreshToken(),
name: localStorage.getItem('name'),
}),
})
return response.json()
}
refreshToken() {
if (this.promise) return this.promise
this.promise = new Promise(resolve => {
this.refreshAccessToken()
.then(res => {
if (res.code === 0) {
this.setToken(res.accessToken)
resolve(true)
} else {
this.removeToken()
resolve(false)
}
})
.catch(err => {
console.error('Refresh token failed', err)
this.removeToken()
resolve(false)
})
})
this.promise.finally(() => {
this.promise = null
})
return this.promise
}
}
const tokener = new TokenManager()
export default tokener
在响应拦截中使用刷新token
import tokener from './tokenManager.js'
const request = async (url, options = {}) => {
const config = {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
}
const token = localStorage.getItem('accessToken')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
try {
const response = await fetch(url, config)
if (response.status === 401 && !config.headers['X-Refresh-Token']) {
const isRefreshSuccess = await tokener.refreshToken()
if (isRefreshSuccess) {
const newToken = localStorage.getItem('accessToken')
config.headers['Authorization'] = `Bearer ${newToken}`
return fetch(url, config).then(res => res.json())
} else {
throw new Error('Token refresh failed')
}
}
return response.json()
} catch (error) {
console.error('Request failed:', error)
throw error
}
}
export default request