浏览器存储配额管理:智能清理与容量优化策略概述浏览器存储配额管理是现代Web应用面临的重要挑战。随着应用数据量的增长,如何有效管理存储空间、实现智能清理和容量优化变得至关重要。本文将深入探讨浏览器存储配额管理机制,实现智能清理算法与容量优化策略。存储配额检测与监控1. 配额检测管理器interface StorageQuota { quota: number; usage: number; usageDetails?: Record<string, number>; } interface StorageEstimate extends StorageQuota { available: number; usagePercentage: number; warningLevel: 'low' | 'medium' | 'high' | 'critical'; } class StorageQuotaManager { private estimates: Map<string, StorageEstimate>; private listeners: Set<(estimate: StorageEstimate) => void>; private monitoringInterval: number; private updateInterval: NodeJS.Timeout | null; constructor(monitoringInterval: number = 30000) { // 30秒 this.estimates = new Map(); this.listeners = new Set(); this.monitoringInterval = monitoringInterval; this.updateInterval = null; } async initialize(): Promise<void> { await this.updateAllEstimates(); this.startMonitoring(); } async getEstimate(origin?: string): Promise<StorageEstimate> { const targetOrigin = origin || window.location.origin; if (!this.estimates.has(targetOrigin)) { await this.updateEstimate(targetOrigin); } return this.estimates.get(targetOrigin)!; } private async updateEstimate(origin: string): Promise<void> { try { if ('storage' in navigator && 'estimate' in navigator.storage) { const estimate = await navigator.storage.estimate(); const enhancedEstimate = this.enhanceEstimate(estimate, origin); this.estimates.set(origin, enhancedEstimate); this.notifyListeners(enhancedEstimate); } else { // 降级方案:使用传统API估算 const fallbackEstimate = await this.getFallbackEstimate(origin); this.estimates.set(origin, fallbackEstimate); this.notifyListeners(fallbackEstimate); } } catch (error) { console.error('Failed to update storage estimate:', error); throw new Error(`Storage estimate unavailable for ${origin}`); } } private enhanceEstimate(estimate: StorageQuota, origin: string): StorageEstimate { const available = estimate.quota - estimate.usage; const usagePercentage = (estimate.usage / estimate.quota) * 100; let warningLevel: 'low' | 'medium' | 'high' | 'critical'; if (usagePercentage >= 90) { warningLevel = 'critical'; } else if (usagePercentage >= 75) { warningLevel = 'high'; } else if (usagePercentage >= 50) { warningLevel = 'medium'; } else { warningLevel = 'low'; } return { ...estimate, available, usagePercentage, warningLevel }; } private async getFallbackEstimate(origin: string): Promise<StorageEstimate> { // 模拟估算逻辑 const quota = this.estimateQuota(); const usage = await this.calculateUsage(); return this.enhanceEstimate({ quota, usage }, origin); } private estimateQuota(): number { // 基于设备和浏览器的配额估算 const deviceInfo = this.getDeviceInfo(); const baseQuota = 50 * 1024 * 1024; // 50MB base switch (deviceInfo.deviceType) { case 'mobile': return baseQuota * 0.5; // 25MB for mobile case 'tablet': return baseQuota * 0.8; // 40MB for tablet case 'desktop': return baseQuota * 2; // 100MB for desktop default: return baseQuota; } } private async calculateUsage(): Promise<number> { let totalUsage = 0; // 计算localStorage使用量 try { for (const key in localStorage) { if (localStorage.hasOwnProperty(key)) { totalUsage += (localStorage[key].length + key.length) * 2; // UTF-16 } } } catch (error) { console.warn('localStorage usage calculation failed:', error); } // 计算IndexedDB使用量 try { const dbUsage = await this.calculateIndexedDBUsage(); totalUsage += dbUsage; } catch (error) { console.warn('IndexedDB usage calculation failed:', error); } // 计算Cache Storage使用量 try { const cacheUsage = await this.calculateCacheStorageUsage(); totalUsage += cacheUsage; } catch (error) { console.warn('Cache Storage usage calculation failed:', error); } return totalUsage; } private async calculateIndexedDBUsage(): Promise<number> { return new Promise((resolve) => { let totalSize = 0; const request = indexedDB.databases(); request.then(async (databases) => { for (const dbInfo of databases) { try { const db = await this.openDatabase(dbInfo.name); const size = await this.calculateDatabaseSize(db); totalSize += size; db.close(); } catch (error) { console.warn(`Failed to calculate size for database ${dbInfo.name}:`, error); } } resolve(totalSize); }).catch(() => resolve(0)); }); } private async calculateCacheStorageUsage(): Promise<number> { try { const cacheNames = await caches.keys(); let totalSize = 0; for (const cacheName of cacheNames) { const cache = await caches.open(cacheName); const requests = await cache.keys(); for (const request of requests) { const response = await cache.match(request); if (response) { const blob = await response.blob(); totalSize += blob.size; } } } return totalSize; } catch (error) { console.warn('Cache Storage calculation failed:', error); return 0; } } private async openDatabase(name: string): Promise<IDBDatabase> { return new Promise((resolve, reject) => { const request = indexedDB.open(name); request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); }); } private async calculateDatabaseSize(db: IDBDatabase): Promise<number> { return new Promise((resolve) => { let totalSize = 0; const transaction = db.transaction(db.objectStoreNames, 'readonly'); let completedStores = 0; const totalStores = db.objectStoreNames.length; if (totalStores === 0) { resolve(0); return; } for (const storeName of db.objectStoreNames) { const objectStore = transaction.objectStore(storeName); const countRequest = objectStore.count(); countRequest.onsuccess = () => { // 粗略估算:每个记录平均1KB totalSize += countRequest.result * 1024; completedStores++; if (completedStores === totalStores) { resolve(totalSize); } }; countRequest.onerror = () => { completedStores++; if (completedStores === totalStores) { resolve(totalSize); } }; } }); } private getDeviceInfo(): DeviceInfo { const userAgent = navigator.userAgent; const width = window.innerWidth; let deviceType: 'mobile' | 'tablet' | 'desktop'; if (width <= 768) { deviceType = 'mobile'; } else if (width <= 1024) { deviceType = 'tablet'; } else { deviceType = 'desktop'; } return { deviceType, userAgent, screenWidth: width, memory: (navigator as any).deviceMemory, cores: navigator.hardwareConcurrency }; } private startMonitoring(): void { this.updateInterval = setInterval(async () => { for (const origin of this.estimates.keys()) { await this.updateEstimate(origin); } }, this.monitoringInterval); } stopMonitoring(): void { if (this.updateInterval) { clearInterval(this.updateInterval); this.updateInterval = null; } } subscribe(listener: (estimate: StorageEstimate) => void): () => void { this.listeners.add(listener); return () => this.listeners.delete(listener); } private notifyListeners(estimate: StorageEstimate): void { this.listeners.forEach(listener => { try { listener(estimate); } catch (error) { console.error('Error in storage quota listener:', error); } }); } } 2. 智能清理策略引擎interface CleanupStrategy { name: string; priority: number; canClean(item: StorageItem): boolean; clean(items: StorageItem[]): Promise<CleanupResult>; } interface StorageItem { key: string; size: number; lastAccessed: number; priority: number; type: 'localStorage' | 'indexedDB' | 'cache' | 'sessionStorage'; metadata?: Record<string, any>; } interface CleanupResult { cleanedItems: number; freedSpace: number; errors: string[]; duration: number; } class IntelligentCleanupEngine { private strategies: CleanupStrategy[]; private storageAnalyzer: StorageAnalyzer; private cleanupHistory: CleanupHistory[]; constructor() { this.strategies = []; this.storageAnalyzer = new StorageAnalyzer(); this.cleanupHistory = []; this.initializeDefaultStrategies(); } private initializeDefaultStrategies(): void { // LRU清理策略 this.addStrategy(new LRUCleanupStrategy()); // 优先级清理策略 this.addStrategy(new PriorityCleanupStrategy()); // 过期数据清理策略 this.addStrategy(new ExpirationCleanupStrategy()); // 大文件清理策略 this.addStrategy(new LargeFileCleanupStrategy()); // 临时数据清理策略 this.addStrategy(new TemporaryDataCleanupStrategy()); } addStrategy(strategy: CleanupStrategy): void { this.strategies.push(strategy); this.strategies.sort((a, b) => b.priority - a.priority); } async performCleanup( targetSize: number, options: CleanupOptions = {} ): Promise<CleanupResult> { const startTime = performance.now(); const items = await this.storageAnalyzer.analyzeStorage(); const currentSize = items.reduce((sum, item) => sum + item.size, 0); if (currentSize <= targetSize) { return { cleanedItems: 0, freedSpace: 0, errors: [], duration: performance.now() - startTime }; } const requiredCleanup = currentSize - targetSize; let totalCleaned = 0; let totalFreed = 0; const errors: string[] = []; // 按策略优先级执行清理 for (const strategy of this.strategies) { if (totalFreed >= requiredCleanup) break; const cleanableItems = items.filter(item => strategy.canClean(item) && !this.isItemProtected(item, options.protectedItems) ); try { const result = await strategy.clean(cleanableItems); totalCleaned += result.cleanedItems; totalFreed += result.freedSpace; errors.push(...result.errors); } catch (error) { errors.push(`Strategy ${strategy.name} failed: ${error}`); } } const duration = performance.now() - startTime; const cleanupResult: CleanupResult = { cleanedItems: totalCleaned, freedSpace: totalFreed, errors, duration }; this.recordCleanupHistory(cleanupResult); return cleanupResult; } private isItemProtected(item: StorageItem, protectedItems?: string[]): boolean { if (!protectedItems) return false; return protectedItems.includes(item.key); } private recordCleanupHistory(result: CleanupResult): void { this.cleanupHistory.push({ ...result, timestamp: Date.now() }); // 保留最近100条记录 if (this.cleanupHistory.length > 100) { this.cleanupHistory = this.cleanupHistory.slice(-100); } } getCleanupHistory(): CleanupHistory[] { return [...this.cleanupHistory]; } predictCleanupEffect(itemsToClean: StorageItem[]): PredictedEffect { const totalSize = itemsToClean.reduce((sum, item) => sum + item.size, 0); const estimatedTime = this.estimateCleanupTime(itemsToClean.length); const riskLevel = this.assessCleanupRisk(itemsToClean); return { freedSpace: totalSize, estimatedTime, riskLevel, recommendations: this.generateRecommendations(itemsToClean) }; } private estimateCleanupTime(itemCount: number): number { // 基于历史数据估算清理时间 const avgTimePerItem = 10; // 平均每个项目10ms return itemCount * avgTimePerItem; } private assessCleanupRisk(items: StorageItem[]): 'low' | 'medium' | 'high' { const hasHighPriorityItems = items.some(item => item.priority >= 8); const hasRecentItems = items.some(item => Date.now() - item.lastAccessed < 24 * 60 * 60 * 1000 ); const hasLargeItems = items.some(item => item.size > 10 * 1024 * 1024); // 10MB if (hasHighPriorityItems || (hasRecentItems && hasLargeItems)) { return 'high'; } else if (hasRecentItems || hasLargeItems) { return 'medium'; } else { return 'low'; } } private generateRecommendations(items: StorageItem[]): string[] { const recommendations: string[] = []; if (items.some(item => item.priority >= 8)) { recommendations.push('包含高优先级项目,建议谨慎清理'); } if (items.some(item => Date.now() - item.lastAccessed < 60 * 60 * 1000)) { recommendations.push('包含最近访问的项目,可能影响用户体验'); } if (items.some(item => item.size > 50 * 1024 * 1024)) { recommendations.push('包含大文件,清理可能释放大量空间'); } return recommendations; } } // LRU清理策略 class LRUCleanupStrategy implements CleanupStrategy { name = 'LRU (Least Recently Used)'; priority = 100; canClean(item: StorageItem): boolean { // 可以清理任何类型的项目 return true; } async clean(items: StorageItem[]): Promise<CleanupResult> { const startTime = performance.now(); const cleanedItems: StorageItem[] = []; const errors: string[] = []; // 按最后访问时间排序(最久未使用的优先清理) const sortedItems = [...items].sort((a, b) => a.lastAccessed - b.lastAccessed); for (const item of sortedItems) { try { await this.cleanItem(item); cleanedItems.push(item); } catch (error) { errors.push(`Failed to clean ${item.key}: ${error}`); } } const totalFreed = cleanedItems.reduce((sum, item) => sum + item.size, 0); const duration = performance.now() - startTime; return { cleanedItems: cleanedItems.length, freedSpace: totalFreed, errors, duration }; } private async cleanItem(item: StorageItem): Promise<void> { switch (item.type) { case 'localStorage': localStorage.removeItem(item.key); break; case 'sessionStorage': sessionStorage.removeItem(item.key); break; case 'indexedDB': await this.cleanIndexedDB(item); break; case 'cache': await this.cleanCache(item); break; default: throw new Error(`Unknown storage type: ${item.type}`); } } private async cleanIndexedDB(item: StorageItem): Promise<void> { return new Promise((resolve, reject) => { const dbName = item.metadata?.dbName; const storeName = item.metadata?.storeName; if (!dbName || !storeName) { reject(new Error('Missing database or store name')); return; } const request = indexedDB.open(dbName); request.onsuccess = (event) => { const db = (event.target as IDBOpenDBRequest).result; if (item.metadata?.key !== undefined) { // 删除特定记录 const transaction = db.transaction([storeName], 'readwrite'); const store = transaction.objectStore(storeName); const deleteRequest = store.delete(item.metadata.key); deleteRequest.onsuccess = () => resolve(); deleteRequest.onerror = () => reject(deleteRequest.error); } else { // 清空整个存储 const transaction = db.transaction([storeName], 'readwrite'); const store = transaction.objectStore(storeName); const clearRequest = store.clear(); clearRequest.onsuccess = () => resolve(); clearRequest.onerror = () => reject(clearRequest.error); } }; request.onerror = () => reject(request.error); }); } private async cleanCache(item: StorageItem): Promise<void> { const cacheName = item.metadata?.cacheName; if (!cacheName) { throw new Error('Missing cache name'); } const cache = await caches.open(cacheName); if (item.metadata?.url) { // 删除特定缓存 await cache.delete(item.metadata.url); } else { // 清空整个缓存 const requests = await cache.keys(); await Promise.all(requests.map(request => cache.delete(request))); } } } // 优先级清理策略 class PriorityCleanupStrategy implements CleanupStrategy { name = 'Priority-based'; priority = 90; canClean(item: StorageItem): boolean { // 只清理优先级低于5的项目 return item.priority < 5; } async clean(items: StorageItem[]): Promise<CleanupResult> { const startTime = performance.now(); const cleanableItems = items.filter(item => this.canClean(item)); // 按优先级排序(优先级低的优先清理) const sortedItems = cleanableItems.sort((a, b) => a.priority - b.priority); const cleanedItems: StorageItem[] = []; const errors: string[] = []; for (const item of sortedItems) { try { await this.cleanItem(item); cleanedItems.push(item); } catch (error) { errors.push(`Failed to clean ${item.key}: ${error}`); } } const totalFreed = cleanedItems.reduce((sum, item) => sum + item.size, 0); const duration = performance.now() - startTime; return { cleanedItems: cleanedItems.length, freedSpace: totalFreed, errors, duration }; } private async cleanItem(item: StorageItem): Promise<void> { // 实现与LRU策略类似的清理逻辑 const lruStrategy = new LRUCleanupStrategy(); await lruStrategy.clean([item]); } } 3. 智能容量优化器interface OptimizationStrategy { name: string; optimize(items: StorageItem[]): Promise<OptimizationResult>; } interface OptimizationResult { optimizedItems: number; spaceSaved: number; compressionRatio: number; duration: number; } class SmartCapacityOptimizer { private strategies: OptimizationStrategy[]; private compressionManager: CompressionManager; private deduplicationEngine: DeduplicationEngine; constructor() { this.strategies = []; this.compressionManager = new CompressionManager(); this.deduplicationEngine = new DeduplicationEngine(); this.initializeStrategies(); } private initializeStrategies(): void { this.strategies.push(new CompressionOptimizationStrategy(this.compressionManager)); this.strategies.push(new DeduplicationOptimizationStrategy(this.deduplicationEngine)); this.strategies.push(new FormatOptimizationStrategy()); this.strategies.push(new MetadataOptimizationStrategy()); } async optimizeStorage(items: StorageItem[]): Promise<OptimizationResult> { const startTime = performance.now(); let totalOptimized = 0; let totalSaved = 0; let totalCompressionRatio = 0; for (const strategy of this.strategies) { try { const result = await strategy.optimize(items); totalOptimized += result.optimizedItems; totalSaved += result.spaceSaved; totalCompressionRatio += result.compressionRatio; } catch (error) { console.error(`Optimization strategy ${strategy.name} failed:`, error); } } const duration = performance.now() - startTime; const avgCompressionRatio = totalCompressionRatio / this.strategies.length; return { optimizedItems: totalOptimized, spaceSaved: totalSaved, compressionRatio: avgCompressionRatio, duration }; } async autoOptimize(targetRatio: number = 0.8): Promise<AutoOptimizationResult> { const items = await this.storageAnalyzer.analyzeStorage(); const currentUsage = items.reduce((sum, item) => sum + item.size, 0); const optimizationResult = await this.optimizeStorage(items); const newUsage = currentUsage - optimizationResult.spaceSaved; const achievedRatio = newUsage / currentUsage; return { ...optimizationResult, targetRatio, achievedRatio, success: achievedRatio <= targetRatio, recommendations: this.generateOptimizationRecommendations(optimizationResult) }; } private generateOptimizationRecommendations(result: OptimizationResult): string[] { const recommendations: string[] = []; if (result.compressionRatio > 0.5) { recommendations.push('压缩效果显著,建议继续使用压缩策略'); } if (result.spaceSaved > 10 * 1024 * 1024) { // 10MB recommendations.push('优化节省了大量空间,考虑定期进行优化'); } if (result.duration > 5000) { // 5秒 recommendations.push('优化耗时较长,建议在后台或低峰期执行'); } return recommendations; } } // 压缩优化策略 class CompressionOptimizationStrategy implements OptimizationStrategy { name = 'Compression'; constructor(private compressionManager: CompressionManager) {} async optimize(items: StorageItem[]): Promise<OptimizationResult> { const compressibleItems = items.filter(item => this.isCompressible(item) && item.size > 1024 // 只压缩大于1KB的项目 ); let totalSaved = 0; let totalCompressed = 0; for (const item of compressibleItems) { try { const originalData = await this.getItemData(item); const compressedData = await this.compressionManager.compress(originalData); const saved = originalData.byteLength - compressedData.byteLength; if (saved > 0) { await this.saveCompressedItem(item, compressedData); totalSaved += saved; totalCompressed++; } } catch (error) { console.warn(`Failed to compress ${item.key}:`, error); } } const compressionRatio = totalCompressed > 0 ? totalSaved / compressibleItems.reduce((sum, item) => sum + item.size, 0) : 0; return { optimizedItems: totalCompressed, spaceSaved: totalSaved, compressionRatio, duration: 0 // 将在上层计算 }; } private isCompressible(item: StorageItem): boolean { // 文本、JSON、XML等格式可以压缩 const compressibleTypes = ['text/plain', 'application/json', 'text/xml', 'text/css', 'text/javascript']; return compressibleTypes.includes(item.metadata?.contentType); } private async getItemData(item: StorageItem): Promise<ArrayBuffer> { // 根据项目类型获取数据 switch (item.type) { case 'localStorage': case 'sessionStorage': return new TextEncoder().encode(localStorage.getItem(item.key) || '').buffer; case 'indexedDB': return await this.getIndexedDBData(item); case 'cache': return await this.getCacheData(item); default: throw new Error(`Unsupported item type: ${item.type}`); } } private async saveCompressedItem(item: StorageItem, compressedData: ArrayBuffer): Promise<void> { // 保存压缩后的数据,并标记为已压缩 // 具体实现取决于存储类型 } } 4. 配额预警系统interface QuotaAlert { id: string; type: 'warning' | 'critical' | 'emergency'; threshold: number; message: string; actions: AlertAction[]; timestamp: number; } interface AlertAction { id: string; label: string; action: () => Promise<void>; type: 'immediate' | 'scheduled'; } class QuotaAlertSystem { private alerts: Map<string, QuotaAlert>; private activeAlerts: Set<string>; private listeners: Set<(alert: QuotaAlert) => void>; private quotaManager: StorageQuotaManager; private cleanupEngine: IntelligentCleanupEngine; constructor( quotaManager: StorageQuotaManager, cleanupEngine: IntelligentCleanupEngine ) { this.alerts = new Map(); this.activeAlerts = new Set(); this.listeners = new Set(); this.quotaManager = quotaManager; this.cleanupEngine = cleanupEngine; this.initializeDefaultAlerts(); } private initializeDefaultAlerts(): void { // 警告级别 - 使用率75% this.addAlert({ id: 'quota-warning', type: 'warning', threshold: 75, message: '存储空间使用率已达到75%,建议进行清理', actions: [ { id: 'analyze-usage', label: '分析使用情况', action: async () => { const estimate = await this.quotaManager.getEstimate(); console.log('Current usage analysis:', estimate); }, type: 'immediate' }, { id: 'schedule-cleanup', label: '计划清理', action: async () => { // 安排后台清理任务 setTimeout(async () => { await this.performAutomaticCleanup(60); // 清理到60%使用率 }, 5000); }, type: 'scheduled' } ], timestamp: Date.now() }); // 严重级别 - 使用率90% this.addAlert({ id: 'quota-critical', type: 'critical', threshold: 90, message: '存储空间使用率已达到90%,需要立即清理', actions: [ { id: 'immediate-cleanup', label: '立即清理', action: async () => { await this.performAutomaticCleanup(70); // 清理到70%使用率 }, type: 'immediate' }, { id: 'optimize-storage', label: '优化存储', action: async () => { const optimizer = new SmartCapacityOptimizer(); await optimizer.autoOptimize(0.8); }, type: 'immediate' } ], timestamp: Date.now() }); // 紧急级别 - 使用率95% this.addAlert({ id: 'quota-emergency', type: 'emergency', threshold: 95, message: '存储空间使用率已达到95%,必须立即采取行动', actions: [ { id: 'emergency-cleanup', label: '紧急清理', action: async () => { await this.performEmergencyCleanup(); }, type: 'immediate' }, { id: 'clear-temp-data', label: '清除临时数据', action: async () => { await this.clearTemporaryData(); }, type: 'immediate' } ], timestamp: Date.now() }); } addAlert(alert: QuotaAlert): void { this.alerts.set(alert.id, alert); } async checkAndTriggerAlerts(estimate: StorageEstimate): Promise<void> { const usagePercentage = estimate.usagePercentage; for (const [alertId, alert] of this.alerts) { if (usagePercentage >= alert.threshold && !this.activeAlerts.has(alertId)) { await this.triggerAlert(alert, estimate); } else if (usagePercentage < alert.threshold && this.activeAlerts.has(alertId)) { this.dismissAlert(alertId); } } } private async triggerAlert(alert: QuotaAlert, estimate: StorageEstimate): Promise<void> { this.activeAlerts.add(alert.id); // 显示通知 await this.showNotification(alert, estimate); // 记录日志 this.logAlert(alert, estimate); // 通知监听器 this.notifyListeners(alert); // 执行自动操作 await this.executeAutoActions(alert); } private dismissAlert(alertId: string): void { this.activeAlerts.delete(alertId); console.log(`Alert ${alertId} dismissed`); } private async showNotification(alert: QuotaAlert, estimate: StorageEstimate): Promise<void> { if ('Notification' in window && Notification.permission === 'granted') { new Notification(`存储空间${alert.type}`, { body: `${alert.message} (当前使用率: ${estimate.usagePercentage.toFixed(1)}%)`, icon: '/icons/storage-alert.png', tag: alert.id, requireInteraction: alert.type === 'emergency' }); } } private logAlert(alert: QuotaAlert, estimate: StorageEstimate): void { console.warn(`[${alert.type.toUpperCase()}] ${alert.message}`, { alertId: alert.id, usagePercentage: estimate.usagePercentage, usage: estimate.usage, quota: estimate.quota, timestamp: new Date().toISOString() }); } private notifyListeners(alert: QuotaAlert): void { this.listeners.forEach(listener => { try { listener(alert); } catch (error) { console.error('Error in alert listener:', error); } }); } private async executeAutoActions(alert: QuotaAlert): Promise<void> { const autoActions = alert.actions.filter(action => action.type === 'immediate'); for (const action of autoActions) { try { console.log(`Executing auto action: ${action.label}`); await action.action(); } catch (error) { console.error(`Auto action failed: ${action.id}`, error); } } } private async performAutomaticCleanup(targetUsagePercentage: number): Promise<void> { const estimate = await this.quotaManager.getEstimate(); const targetSize = (estimate.quota * targetUsagePercentage) / 100; console.log(`Performing automatic cleanup to reach ${targetUsagePercentage}% usage`); const result = await this.cleanupEngine.performCleanup(targetSize); console.log('Automatic cleanup completed:', { cleanedItems: result.cleanedItems, freedSpace: this.formatBytes(result.freedSpace), duration: `${result.duration.toFixed(2)}ms` }); } private async performEmergencyCleanup(): Promise<void> { console.log('Performing emergency cleanup...'); // 获取当前使用情况 const estimate = await this.quotaManager.getEstimate(); const emergencyTarget = estimate.quota * 0.6; // 目标60%使用率 // 执行激进清理 const result = await this.cleanupEngine.performCleanup(emergencyTarget, { aggressive: true, includeTemporary: true, includeCache: true }); // 如果清理效果不佳,执行更激进的措施 if (result.freedSpace < estimate.usage * 0.2) { await this.performAggressiveCleanup(); } console.log('Emergency cleanup completed:', result); } private async performAggressiveCleanup(): Promise<void> { console.log('Performing aggressive cleanup...'); // 清理IndexedDB中的非关键数据 await this.clearNonCriticalIndexedDB(); // 清理缓存存储 await this.clearAllCache(); // 清理localStorage中的非必要数据 await this.clearNonEssentialLocalStorage(); } private async clearTemporaryData(): Promise<void> { const tempPatterns = [ /^temp_/, /^cache_/, /^session_/, /_tmp$/, /_temp$/ ]; // 清理localStorage中的临时数据 for (const key in localStorage) { if (tempPatterns.some(pattern => pattern.test(key))) { localStorage.removeItem(key); } } // 清理sessionStorage sessionStorage.clear(); console.log('Temporary data cleared'); } private async clearNonCriticalIndexedDB(): Promise<void> { try { const databases = await indexedDB.databases(); const nonCriticalDBs = databases.filter(db => !db.name?.includes('critical') && !db.name?.includes('essential') ); for (const db of nonCriticalDBs) { if (db.name) { indexedDB.deleteDatabase(db.name); } } console.log(`Cleared ${nonCriticalDBs.length} non-critical databases`); } catch (error) { console.error('Failed to clear non-critical IndexedDB:', error); } } private async clearAllCache(): Promise<void> { try { const cacheNames = await caches.keys(); await Promise.all(cacheNames.map(name => caches.delete(name))); console.log(`Cleared ${cacheNames.length} cache storages`); } catch (error) { console.error('Failed to clear cache storages:', error); } } private async clearNonEssentialLocalStorage(): Promise<void> { const essentialKeys = [ 'user_token', 'user_preferences', 'app_config', 'authentication' ]; const keysToRemove: string[] = []; for (const key in localStorage) { if (!essentialKeys.includes(key)) { keysToRemove.push(key); } } keysToRemove.forEach(key => localStorage.removeItem(key)); console.log(`Cleared ${keysToRemove.length} non-essential localStorage items`); } subscribe(listener: (alert: QuotaAlert) => void): () => void { this.listeners.add(listener); return () => this.listeners.delete(listener); } private formatBytes(bytes: number): string { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } } // 使用示例 class StorageQuotaDemo { private quotaManager: StorageQuotaManager; private cleanupEngine: IntelligentCleanupEngine; private optimizer: SmartCapacityOptimizer; private alertSystem: QuotaAlertSystem; constructor() { this.quotaManager = new StorageQuotaManager(); this.cleanupEngine = new IntelligentCleanupEngine(); this.optimizer = new SmartCapacityOptimizer(); this.alertSystem = new QuotaAlertSystem(this.quotaManager, this.cleanupEngine); } async initialize(): Promise<void> { await this.quotaManager.initialize(); // 设置配额监控 this.quotaManager.subscribe(async (estimate) => { await this.alertSystem.checkAndTriggerAlerts(estimate); }); console.log('Storage quota management system initialized'); } async demonstrateCleanup(): Promise<void> { const estimate = await this.quotaManager.getEstimate(); console.log('Current storage usage:', estimate); // 执行智能清理 const targetSize = estimate.usage * 0.7; // 目标减少到70% const cleanupResult = await this.cleanupEngine.performCleanup(targetSize); console.log('Cleanup result:', cleanupResult); } async demonstrateOptimization(): Promise<void> { const result = await this.optimizer.autoOptimize(0.8); console.log('Optimization result:', result); } } 总结浏览器存储配额管理是现代Web应用必须面对的重要挑战。通过实现智能清理算法、容量优化策略和配额预警系统,我们可以:智能监控:实时监控存储使用情况,提供准确的配额估算主动清理:基于多种策略的智能清理,确保存储空间的有效利用容量优化:通过压缩、去重等技术手段最大化存储效率预警机制:多级别的配额预警,防止存储空间耗尽自动化管理:自动执行清理和优化任务,减少人工干预这套完整的存储配额管理体系能够显著提升Web应用的可靠性和用户体验。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部