浏览器存储配额管理:智能清理与容量优化策略概述浏览器存储配额管理是现代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 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部