优化sse
This commit is contained in:
@@ -73,7 +73,7 @@ function rejectPendingRequests(scope: AuthScope, error: unknown) {
|
||||
pendingRequests.forEach(({ reject }) => reject(error))
|
||||
}
|
||||
|
||||
async function refreshToken(scope: AuthScope): Promise<string> {
|
||||
export async function refreshAccessToken(scope: AuthScope): Promise<string> {
|
||||
const refreshToken = getRefreshToken(scope)
|
||||
if (!refreshToken) throw new Error('no refresh token')
|
||||
|
||||
@@ -153,7 +153,7 @@ apiClient.interceptors.response.use(
|
||||
|
||||
state.refreshing = true
|
||||
try {
|
||||
const newToken = await refreshToken(scope)
|
||||
const newToken = await refreshAccessToken(scope)
|
||||
resolvePendingRequests(scope, newToken)
|
||||
originalRequest._retry = true
|
||||
originalRequest.headers.Authorization = `Bearer ${newToken}`
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { onBeforeUnmount, ref, type Ref } from 'vue'
|
||||
import { refreshAccessToken } from '@/api/client'
|
||||
import { getAccessToken, type AuthScope } from '@/utils/authStorage'
|
||||
|
||||
export interface SSEMessage {
|
||||
@@ -29,6 +30,7 @@ export function useChatSSE(scope: AuthScope, endpoint: string) {
|
||||
let source: EventSource | null = null
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let stopped = false
|
||||
let refreshing = false
|
||||
const handlers: EventHandler[] = []
|
||||
|
||||
function onEvent(handler: EventHandler) {
|
||||
@@ -36,6 +38,7 @@ export function useChatSSE(scope: AuthScope, endpoint: string) {
|
||||
}
|
||||
|
||||
function connect() {
|
||||
if (stopped || source) return
|
||||
const token = getAccessToken(scope)
|
||||
if (!token) return
|
||||
|
||||
@@ -60,18 +63,27 @@ export function useChatSSE(scope: AuthScope, endpoint: string) {
|
||||
} catch { /* ignore */ }
|
||||
})
|
||||
|
||||
source.onerror = () => {
|
||||
source.onerror = async () => {
|
||||
connected.value = false
|
||||
source?.close()
|
||||
source = null
|
||||
if (!stopped) {
|
||||
reconnectTimer = setTimeout(connect, reconnectDelay)
|
||||
if (stopped || refreshing) return
|
||||
|
||||
refreshing = true
|
||||
try {
|
||||
await refreshAccessToken(scope)
|
||||
if (!stopped) {
|
||||
reconnectTimer = setTimeout(connect, reconnectDelay)
|
||||
}
|
||||
} catch {
|
||||
closeSource()
|
||||
} finally {
|
||||
refreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
stopped = true
|
||||
function closeSource() {
|
||||
if (reconnectTimer) {
|
||||
clearTimeout(reconnectTimer)
|
||||
reconnectTimer = null
|
||||
@@ -81,6 +93,21 @@ export function useChatSSE(scope: AuthScope, endpoint: string) {
|
||||
connected.value = false
|
||||
}
|
||||
|
||||
function handleAuthStorageChanged(event: Event) {
|
||||
const detail = (event as CustomEvent<{ scope?: AuthScope }>).detail
|
||||
if (detail?.scope !== scope || stopped) return
|
||||
closeSource()
|
||||
connect()
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
stopped = true
|
||||
closeSource()
|
||||
window.removeEventListener('auth-storage-changed', handleAuthStorageChanged)
|
||||
}
|
||||
|
||||
window.addEventListener('auth-storage-changed', handleAuthStorageChanged)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
disconnect()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user