优化
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
export interface CrossTabRefreshOptions<T> {
|
||||
lockName: string
|
||||
observedRefreshToken: string
|
||||
currentRefreshToken: () => string
|
||||
reuseCurrentSession: () => Promise<T>
|
||||
refresh: (refreshToken: string) => Promise<T>
|
||||
}
|
||||
|
||||
export async function coordinateCrossTabRefresh<T>(options: CrossTabRefreshOptions<T>): Promise<T> {
|
||||
const run = async () => {
|
||||
const currentRefreshToken = options.currentRefreshToken()
|
||||
if (currentRefreshToken && currentRefreshToken !== options.observedRefreshToken) {
|
||||
return options.reuseCurrentSession()
|
||||
}
|
||||
return options.refresh(currentRefreshToken || options.observedRefreshToken)
|
||||
}
|
||||
|
||||
if (typeof navigator === 'undefined' || !navigator.locks) {
|
||||
try {
|
||||
return await run()
|
||||
} catch (error) {
|
||||
if (!options.currentRefreshToken()) throw error
|
||||
// Web Locks requires a secure context. On plain HTTP, briefly allow another tab's
|
||||
// successful rotation to reach shared storage before treating this session as expired.
|
||||
for (let attempt = 0; attempt < 20; attempt += 1) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
const currentRefreshToken = options.currentRefreshToken()
|
||||
if (!currentRefreshToken) throw error
|
||||
if (currentRefreshToken && currentRefreshToken !== options.observedRefreshToken) {
|
||||
return options.reuseCurrentSession()
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
return navigator.locks.request(options.lockName, run)
|
||||
}
|
||||
Reference in New Issue
Block a user