|
import { apiPrefix } from '@/config' |
|
import { fetchWithRetry } from '@/utils' |
|
|
|
let isRefreshing = false |
|
function waitUntilTokenRefreshed() { |
|
return new Promise<void>((resolve, reject) => { |
|
function _check() { |
|
const isRefreshingSign = localStorage.getItem('is_refreshing') |
|
if ((isRefreshingSign && isRefreshingSign === '1') || isRefreshing) { |
|
setTimeout(() => { |
|
_check() |
|
}, 1000) |
|
} |
|
else { |
|
resolve() |
|
} |
|
} |
|
_check() |
|
}) |
|
} |
|
|
|
|
|
async function getNewAccessToken(): Promise<void> { |
|
try { |
|
const isRefreshingSign = localStorage.getItem('is_refreshing') |
|
if ((isRefreshingSign && isRefreshingSign === '1') || isRefreshing) { |
|
await waitUntilTokenRefreshed() |
|
} |
|
else { |
|
globalThis.localStorage.setItem('is_refreshing', '1') |
|
isRefreshing = true |
|
const refresh_token = globalThis.localStorage.getItem('refresh_token') |
|
|
|
|
|
|
|
|
|
|
|
|
|
const [error, ret] = await fetchWithRetry(globalThis.fetch(`${apiPrefix}/refresh-token`, { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json;utf-8', |
|
}, |
|
body: JSON.stringify({ refresh_token }), |
|
})) |
|
if (error) { |
|
return Promise.reject(error) |
|
} |
|
else { |
|
if (ret.status === 401) |
|
return Promise.reject(ret) |
|
|
|
const { data } = await ret.json() |
|
globalThis.localStorage.setItem('console_token', data.access_token) |
|
globalThis.localStorage.setItem('refresh_token', data.refresh_token) |
|
} |
|
} |
|
} |
|
catch (error) { |
|
console.error(error) |
|
return Promise.reject(error) |
|
} |
|
finally { |
|
isRefreshing = false |
|
globalThis.localStorage.removeItem('is_refreshing') |
|
} |
|
} |
|
|
|
export async function refreshAccessTokenOrRelogin(timeout: number) { |
|
return Promise.race([new Promise<void>((resolve, reject) => setTimeout(() => { |
|
isRefreshing = false |
|
globalThis.localStorage.removeItem('is_refreshing') |
|
reject(new Error('request timeout')) |
|
}, timeout)), getNewAccessToken()]) |
|
} |
|
|