This commit is contained in:
jxxghp
2025-07-07 15:17:16 +08:00
parent 44d78fd2ea
commit 3cfe27b7b3
2 changed files with 52 additions and 174 deletions

View File

@@ -7,7 +7,6 @@ import { addBackgroundTimer, removeBackgroundTimer } from '@/utils/backgroundMan
* 统一管理SSE连接和定时器优化iOS后台性能
*/
export function useBackgroundOptimization() {
/**
* 使用优化的SSE连接
* @param url SSE连接地址
@@ -16,29 +15,29 @@ export function useBackgroundOptimization() {
* @param options 选项
*/
const useSSE = (
url: string,
messageHandler: (event: MessageEvent) => void,
url: string,
messageHandler: (event: MessageEvent) => void,
listenerId: string,
options?: {
backgroundCloseDelay?: number
reconnectDelay?: number
maxReconnectAttempts?: number
}
},
) => {
const manager = sseManagerSingleton.getManager(url, options)
onMounted(() => {
manager.addMessageListener(listenerId, messageHandler)
})
onUnmounted(() => {
manager.removeMessageListener(listenerId)
})
return {
manager,
readyState: () => manager.readyState,
close: () => manager.removeMessageListener(listenerId)
close: () => manager.removeMessageListener(listenerId),
}
}
@@ -56,18 +55,18 @@ export function useBackgroundOptimization() {
options?: {
runInBackground?: boolean
skipInitialRun?: boolean
}
},
) => {
onMounted(() => {
addBackgroundTimer(id, callback, interval, options)
})
onUnmounted(() => {
removeBackgroundTimer(id)
})
return {
remove: () => removeBackgroundTimer(id)
remove: () => removeBackgroundTimer(id),
}
}
@@ -84,24 +83,24 @@ export function useBackgroundOptimization() {
messageHandler: (event: MessageEvent) => void,
listenerId: string,
delay: number = 3000,
options?: Parameters<typeof useSSE>[3]
options?: Parameters<typeof useSSE>[3],
) => {
const manager = sseManagerSingleton.getManager(url, options)
onMounted(() => {
setTimeout(() => {
manager.addMessageListener(listenerId, messageHandler)
}, delay)
})
onUnmounted(() => {
manager.removeMessageListener(listenerId)
})
return {
manager,
readyState: () => manager.readyState,
close: () => manager.removeMessageListener(listenerId)
close: () => manager.removeMessageListener(listenerId),
}
}
@@ -116,32 +115,32 @@ export function useBackgroundOptimization() {
url: string,
messageHandler: (event: MessageEvent) => void,
listenerId: string,
isActive: Ref<boolean>
isActive: Ref<boolean>,
) => {
const manager = sseManagerSingleton.getManager(url, {
backgroundCloseDelay: 1000, // 进度SSE更快关闭
reconnectDelay: 1000,
maxReconnectAttempts: 5
maxReconnectAttempts: 5,
})
const startProgress = () => {
if (isActive.value) {
manager.addMessageListener(listenerId, messageHandler)
}
}
const stopProgress = () => {
manager.removeMessageListener(listenerId)
}
onUnmounted(() => {
stopProgress()
})
return {
start: startProgress,
stop: stopProgress,
manager
manager,
}
}
@@ -156,13 +155,13 @@ export function useBackgroundOptimization() {
id: string,
loadDataFunc: () => Promise<void> | void,
interval: number = 3000,
immediate: boolean = true
immediate: boolean = true,
) => {
const loading = ref(false)
const wrappedLoadData = async () => {
if (loading.value) return
loading.value = true
try {
await loadDataFunc()
@@ -172,31 +171,26 @@ export function useBackgroundOptimization() {
loading.value = false
}
}
onMounted(async () => {
if (immediate) {
await wrappedLoadData()
}
addBackgroundTimer(
id,
wrappedLoadData,
interval,
{
runInBackground: false, // 后台不刷新数据
skipInitialRun: true // 已经手动执行过了
}
)
addBackgroundTimer(id, wrappedLoadData, interval, {
runInBackground: false, // 后台不刷新数据
skipInitialRun: true, // 已经手动执行过了
})
})
onUnmounted(() => {
removeBackgroundTimer(id)
})
return {
loading,
refresh: wrappedLoadData,
stop: () => removeBackgroundTimer(id)
stop: () => removeBackgroundTimer(id),
}
}
@@ -213,14 +207,14 @@ export function useBackgroundOptimization() {
loadDataFunc: () => Promise<void> | void,
condition: Ref<boolean>,
interval: number = 3000,
immediate: boolean = true
immediate: boolean = true,
) => {
const loading = ref(false)
const isTimerActive = ref(false)
const wrappedLoadData = async () => {
if (loading.value || !condition.value) return
loading.value = true
try {
await loadDataFunc()
@@ -233,15 +227,10 @@ export function useBackgroundOptimization() {
const startTimer = () => {
if (!isTimerActive.value && condition.value) {
addBackgroundTimer(
id,
wrappedLoadData,
interval,
{
runInBackground: false,
skipInitialRun: !immediate
}
)
addBackgroundTimer(id, wrappedLoadData, interval, {
runInBackground: false,
skipInitialRun: !immediate,
})
isTimerActive.value = true
}
}
@@ -252,12 +241,12 @@ export function useBackgroundOptimization() {
isTimerActive.value = false
}
}
onMounted(() => {
if (condition.value) {
startTimer()
}
// 监听条件变化
watch(condition, (newValue: boolean) => {
if (newValue) {
@@ -267,17 +256,17 @@ export function useBackgroundOptimization() {
}
})
})
onUnmounted(() => {
stopTimer()
})
return {
loading,
refresh: wrappedLoadData,
stop: stopTimer,
start: startTimer,
isActive: isTimerActive
isActive: isTimerActive,
}
}
@@ -287,6 +276,6 @@ export function useBackgroundOptimization() {
useDelayedSSE,
useProgressSSE,
useDataRefresh,
useConditionalDataRefresh
useConditionalDataRefresh,
}
}
}

View File

@@ -13,10 +13,6 @@ const options = {
// 存储未读消息数量的键名
const UNREAD_COUNT_KEY = 'mp_unread_count'
// 状态管理相关的缓存名称和端点
const STATE_CACHE_NAME = 'mp-pwa-state-cache'
const STATE_ENDPOINT = '/api/pwa-state'
// 从IndexedDB获取未读消息数量
async function getStoredUnreadCount(): Promise<number> {
try {
@@ -37,60 +33,6 @@ async function setStoredUnreadCount(count: number): Promise<void> {
}
}
// 保存PWA状态到缓存
async function saveStateToCache(request: Request): Promise<Response> {
try {
const state = await request.json()
const cache = await caches.open(STATE_CACHE_NAME)
await cache.put(
STATE_ENDPOINT,
new Response(
JSON.stringify({
...state,
timestamp: Date.now(),
}),
),
)
return new Response(JSON.stringify({ success: true }))
} catch (error) {
console.error('Failed to save state to cache:', error)
return new Response(
JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }),
{
status: 500,
headers: { 'Content-Type': 'application/json' },
},
)
}
}
// 从缓存获取PWA状态
async function getStateFromCache(): Promise<Response> {
try {
const cache = await caches.open(STATE_CACHE_NAME)
const response = await cache.match(STATE_ENDPOINT)
if (response) {
const state = await response.json()
return new Response(JSON.stringify(state), {
headers: { 'Content-Type': 'application/json' },
})
}
return new Response(JSON.stringify({}), {
headers: { 'Content-Type': 'application/json' },
})
} catch (error) {
console.error('Failed to get state from cache:', error)
return new Response(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
})
}
}
// 简单的IndexedDB包装器
async function openDB(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
@@ -158,25 +100,9 @@ async function clearBadge() {
}
// 安装事件
self.addEventListener('install', event => {
event.waitUntil(
(async () => {
// 预缓存关键状态数据
try {
const cache = await caches.open(STATE_CACHE_NAME)
const existingState = await cache.match(STATE_ENDPOINT)
if (existingState) {
// 预热状态数据(无需处理,仅确保缓存可用)
}
} catch (error) {
// 静默处理错误
}
// 强制等待中的Service Worker立即成为活动的Service Worker
self.skipWaiting()
})(),
)
self.addEventListener('install', () => {
// 强制等待中的Service Worker立即成为活动的Service Worker
self.skipWaiting()
})
// 激活事件
@@ -207,16 +133,6 @@ self.addEventListener('activate', event => {
self.addEventListener('fetch', event => {
const url = new URL(event.request.url)
// 处理PWA状态管理请求
if (url.pathname === STATE_ENDPOINT) {
if (event.request.method === 'POST') {
event.respondWith(saveStateToCache(event.request))
} else if (event.request.method === 'GET') {
event.respondWith(getStateFromCache())
}
return
}
if (event.request.url.includes('/api/v1/') && event.request.method === 'GET') {
event.respondWith(
(async () => {
@@ -336,32 +252,5 @@ self.addEventListener('message', function (event) {
.catch(error => {
event.ports[0]?.postMessage({ count: 0 })
})
} else if (event.data && event.data.type === 'SAVE_PWA_STATE') {
// 保存PWA状态
const state = event.data.state || {}
saveStateToCache(
new Request(STATE_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(state),
}),
)
.then(response => response.json())
.then(result => {
event.ports[0]?.postMessage({ success: result.success })
})
.catch(error => {
event.ports[0]?.postMessage({ success: false, error: error instanceof Error ? error.message : String(error) })
})
} else if (event.data && event.data.type === 'GET_PWA_STATE') {
// 获取PWA状态
getStateFromCache()
.then(response => response.json())
.then(state => {
event.ports[0]?.postMessage({ state })
})
.catch(error => {
event.ports[0]?.postMessage({ state: {} })
})
}
})