浏览器存储 API:全面解析与高级实践

浏览器存储 API:全面解析与高级实践

引言

在现代Web开发中,浏览器存储是构建丰富、离线可用、高性能应用的关键技术。从简单的键值对存储到复杂的数据库操作,浏览器提供了多种存储方案。本文将深入探讨各种浏览器存储API,包括它们的特性、使用场景、性能优化和最佳实践。

一、本地存储的现代封装

1.1 增强型 localStorage/sessionStorage 封装
javascript 复制代码
class StorageManager {
  constructor(storageType = 'localStorage') {
    this.storage = window[storageType];
    this.prefix = 'app_';
    this.encryptionEnabled = false;
    this.compressionEnabled = false;
    this.observers = new Map();
    this.expiryTimes = new Map();
    this.cleanupInterval = null;
  }

  // 初始化存储管理器
  init(options = {}) {
    const {
      prefix = 'app_',
      encryptionKey = null,
      compressionThreshold = 1024, // 1KB
      cleanupInterval = 60000 // 1分钟
    } = options;

    this.prefix = prefix;
    
    if (encryptionKey) {
      this.enableEncryption(encryptionKey);
    }
    
    if (compressionThreshold > 0) {
      this.compressionEnabled = true;
      this.compressionThreshold = compressionThreshold;
    }

    // 启动过期数据清理
    this.startCleanupInterval(cleanupInterval);

    // 监听storage事件实现跨标签页同步
    window.addEventListener('storage', this.handleStorageEvent.bind(this));

    return this;
  }

  // 生成带前缀的键名
  getPrefixedKey(key) {
    return `${this.prefix}${key}`;
  }

  // 序列化数据
  serialize(data) {
    const serialized = JSON.stringify({
      data,
      timestamp: Date.now(),
      version: '1.0'
    });

    // 压缩大文本数据
    if (this.compressionEnabled && serialized.length > this.compressionThreshold) {
      return this.compress(serialized);
    }

    return serialized;
  }

  // 反序列化数据
  deserialize(serialized) {
    try {
      let data = serialized;
      
      // 解压缩(如果有压缩)
      if (this.isCompressed(serialized)) {
        data = this.decompress(serialized);
      }

      const parsed = JSON.parse(data);
      
      // 验证数据完整性
      if (!parsed.data || !parsed.timestamp) {
        throw new Error('Invalid data format');
      }

      return parsed.data;
    } catch (error) {
      console.warn('Failed to deserialize data:', error);
      return null;
    }
  }

  // 数据压缩
  compress(text) {
    try {
      // 简单的压缩算法,实际项目中可使用pako等库
      const base64 = btoa(encodeURIComponent(text));
      return `compressed:${base64}`;
    } catch {
      return text;
    }
  }

  // 数据解压缩
  decompress(text) {
    if (!text.startsWith('compressed:')) return text;
    
    try {
      const base64 = text.slice(11);
      return decodeURIComponent(atob(base64));
    } catch {
      return text;
    }
  }

  // 判断是否压缩
  isCompressed(text) {
    return text.startsWith('compressed:');
  }

  // 设置数据
  set(key, value, options = {}) {
    const {
      ttl = null, // 过期时间(毫秒)
      encrypt = false
    } = options;

    try {
      const prefixedKey = this.getPrefixedKey(key);
      let processedValue = value;

      // 加密数据
      if (encrypt && this.encryptionEnabled) {
        processedValue = this.encryptData(value);
      }

      const serialized = this.serialize(processedValue);
      this.storage.setItem(prefixedKey, serialized);

      // 设置过期时间
      if (ttl) {
        const expiryTime = Date.now() + ttl;
        this.expiryTimes.set(prefixedKey, expiryTime);
      }

      // 通知观察者
      this.notifyObservers(key, value, 'set');

      return true;
    } catch (error) {
      console.error('Failed to set storage item:', error);
      return false;
    }
  }

  // 获取数据
  get(key, defaultValue = null) {
    try {
      const prefixedKey = this.getPrefixedKey(key);
      const serialized = this.storage.getItem(prefixedKey);

      if (serialized === null) {
        return defaultValue;
      }

      // 检查是否过期
      if (this.isExpired(prefixedKey)) {
        this.remove(key);
        return defaultValue;
      }

      let data = this.deserialize(serialized);

      // 解密数据
      if (typeof data === 'string' && data.startsWith('encrypted:')) {
        data = this.decryptData(data);
      }

      return data;
    } catch (error) {
      console.error('Failed to get storage item:', error);
      return defaultValue;
    }
  }

  // 删除数据
  remove(key) {
    const prefixedKey = this.getPrefixedKey(key);
    this.storage.removeItem(prefixedKey);
    this.expiryTimes.delete(prefixedKey);
    this.notifyObservers(key, null, 'remove');
    return true;
  }

  // 清空所有数据(保留前缀)
  clear() {
    const keysToRemove = [];
    for (let i = 0; i < this.storage.length; i++) {
      const key = this.storage.key(i);
      if (key.startsWith(this.prefix)) {
        keysToRemove.push(key);
      }
    }

    keysToRemove.forEach(key => {
      this.storage.removeItem(key);
      this.expiryTimes.delete(key);
    });

    this.notifyObservers('*', null, 'clear');
    return true;
  }

  // 检查数据是否过期
  isExpired(key) {
    const expiryTime = this.expiryTimes.get(key);
    if (!expiryTime) return false;
    
    return Date.now() > expiryTime;
  }

  // 启用加密
  enableEncryption(encryptionKey) {
    if (typeof window.crypto === 'undefined') {
      console.warn('Web Crypto API not available, encryption disabled');
      return false;
    }

    this.encryptionEnabled = true;
    this.encryptionKey = encryptionKey;
    return true;
  }

  // 加密数据
  async encryptData(data) {
    try {
      const textEncoder = new TextEncoder();
      const dataBuffer = textEncoder.encode(JSON.stringify(data));
      
      // 生成随机的初始化向量
      const iv = window.crypto.getRandomValues(new Uint8Array(12));
      
      // 导入密钥
      const keyMaterial = await window.crypto.subtle.importKey(
        'raw',
        textEncoder.encode(this.encryptionKey),
        { name: 'PBKDF2' },
        false,
        ['deriveKey']
      );
      
      // 派生密钥
      const key = await window.crypto.subtle.deriveKey(
        {
          name: 'PBKDF2',
          salt: textEncoder.encode('storage-salt'),
          iterations: 100000,
          hash: 'SHA-256'
        },
        keyMaterial,
        { name: 'AES-GCM', length: 256 },
        false,
        ['encrypt', 'decrypt']
      );
      
      // 加密数据
      const encryptedBuffer = await window.crypto.subtle.encrypt(
        {
          name: 'AES-GCM',
          iv: iv
        },
        key,
        dataBuffer
      );
      
      // 组合IV和加密数据
      const combinedBuffer = new Uint8Array(iv.length + encryptedBuffer.byteLength);
      combinedBuffer.set(iv, 0);
      combinedBuffer.set(new Uint8Array(encryptedBuffer), iv.length);
      
      // 转换为base64字符串
      const base64String = btoa(String.fromCharCode.apply(null, combinedBuffer));
      return `encrypted:${base64String}`;
    } catch (error) {
      console.error('Encryption failed:', error);
      return data;
    }
  }

  // 解密数据
  async decryptData(encryptedString) {
    try {
      if (!encryptedString.startsWith('encrypted:')) {
        return encryptedString;
      }
      
      const base64String = encryptedString.slice(10);
      const combinedBuffer = Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
      
      // 提取IV和加密数据
      const iv = combinedBuffer.slice(0, 12);
      const encryptedBuffer = combinedBuffer.slice(12);
      
      const textEncoder = new TextEncoder();
      const keyMaterial = await window.crypto.subtle.importKey(
        'raw',
        textEncoder.encode(this.encryptionKey),
        { name: 'PBKDF2' },
        false,
        ['deriveKey']
      );
      
      const key = await window.crypto.subtle.deriveKey(
        {
          name: 'PBKDF2',
          salt: textEncoder.encode('storage-salt'),
          iterations: 100000,
          hash: 'SHA-256'
        },
        keyMaterial,
        { name: 'AES-GCM', length: 256 },
        false,
        ['encrypt', 'decrypt']
      );
      
      // 解密数据
      const decryptedBuffer = await window.crypto.subtle.decrypt(
        {
          name: 'AES-GCM',
          iv: iv
        },
        key,
        encryptedBuffer
      );
      
      const textDecoder = new TextDecoder();
      const decryptedString = textDecoder.decode(decryptedBuffer);
      return JSON.parse(decryptedString);
    } catch (error) {
      console.error('Decryption failed:', error);
      return encryptedString;
    }
  }

  // 添加观察者
  observe(key, callback) {
    if (!this.observers.has(key)) {
      this.observers.set(key, new Set());
    }
    this.observers.get(key).add(callback);
    
    // 返回取消观察的函数
    return () => {
      const observers = this.observers.get(key);
      if (observers) {
        observers.delete(callback);
        if (observers.size === 0) {
          this.observers.delete(key);
        }
      }
    };
  }

  // 通知观察者
  notifyObservers(key, value, action) {
    // 通知特定键的观察者
    const keyObservers = this.observers.get(key);
    if (keyObservers) {
      keyObservers.forEach(callback => {
        callback(value, action, key);
      });
    }

    // 通知全局观察者
    const globalObservers = this.observers.get('*');
    if (globalObservers) {
      globalObservers.forEach(callback => {
        callback(value, action, key);
      });
    }
  }

  // 处理storage事件
  handleStorageEvent(event) {
    if (event.storageArea !== this.storage) return;
    
    const key = event.key;
    if (key && key.startsWith(this.prefix)) {
      const unprefixedKey = key.slice(this.prefix.length);
      const value = event.newValue ? this.get(unprefixedKey) : null;
      const action = event.newValue ? 'set' : 'remove';
      
      this.notifyObservers(unprefixedKey, value, action);
    }
  }

  // 启动清理定时器
  startCleanupInterval(interval) {
    this.cleanupInterval = setInterval(() => {
      this.cleanupExpired();
    }, interval);
  }

  // 清理过期数据
  cleanupExpired() {
    const now = Date.now();
    const expiredKeys = [];
    
    this.expiryTimes.forEach((expiryTime, key) => {
      if (now > expiryTime) {
        expiredKeys.push(key);
      }
    });
    
    expiredKeys.forEach(key => {
      const unprefixedKey = key.slice(this.prefix.length);
      this.remove(unprefixedKey);
    });
    
    if (expiredKeys.length > 0) {
      console.log(`Cleaned up ${expiredKeys.length} expired items`);
    }
  }

  // 获取存储统计信息
  getStats() {
    let totalSize = 0;
    let itemCount = 0;
    
    for (let i = 0; i < this.storage.length; i++) {
      const key = this.storage.key(i);
      if (key.startsWith(this.prefix)) {
        const value = this.storage.getItem(key);
        totalSize += (key.length + value.length) * 2; // UTF-16字符占2字节
        itemCount++;
      }
    }
    
    return {
      totalSize,
      itemCount,
      estimatedRemaining: 5 * 1024 * 1024 - totalSize, // 假设5MB限制
      usagePercentage: (totalSize / (5 * 1024 * 1024)) * 100
    };
  }

  // 批量操作
  batch(operations) {
    return operations.reduce((results, operation) => {
      const { type, key, value, options } = operation;
      let result;
      
      switch (type) {
        case 'set':
          result = this.set(key, value, options);
          break;
        case 'get':
          result = this.get(key);
          break;
        case 'remove':
          result = this.remove(key);
          break;
        default:
          result = null;
      }
      
      results.push({ key, result });
      return results;
    }, []);
  }

  // 获取所有键
  keys() {
    const keys = [];
    for (let i = 0; i < this.storage.length; i++) {
      const key = this.storage.key(i);
      if (key.startsWith(this.prefix)) {
        keys.push(key.slice(this.prefix.length));
      }
    }
    return keys;
  }

  // 导出所有数据
  export() {
    const data = {};
    for (const key of this.keys()) {
      data[key] = this.get(key);
    }
    return {
      timestamp: Date.now(),
      version: '1.0',
      prefix: this.prefix,
      data
    };
  }

  // 导入数据
  import(data) {
    if (!data || !data.data) {
      throw new Error('Invalid import data');
    }
    
    Object.entries(data.data).forEach(([key, value]) => {
      this.set(key, value);
    });
    
    return true;
  }

  // 销毁实例
  destroy() {
    if (this.cleanupInterval) {
      clearInterval(this.cleanupInterval);
    }
    window.removeEventListener('storage', this.handleStorageEvent);
    this.observers.clear();
    this.expiryTimes.clear();
  }
}

// 使用示例
class StorageExample {
  static async demonstrate() {
    // 创建存储管理器
    const storage = new StorageManager('localStorage');
    
    // 初始化
    storage.init({
      prefix: 'myapp_',
      encryptionKey: 'my-secret-key-123',
      compressionThreshold: 500,
      cleanupInterval: 30000
    });
    
    // 设置带过期时间的数据
    storage.set('user', {
      id: 123,
      name: 'John Doe',
      email: 'john@example.com'
    }, { ttl: 3600000 }); // 1小时后过期
    
    // 设置加密数据
    storage.set('token', 'secret-token-abc', { encrypt: true });
    
    // 获取数据
    const user = storage.get('user');
    const token = storage.get('token');
    
    console.log('User:', user);
    console.log('Token:', token);
    
    // 观察数据变化
    const unsubscribe = storage.observe('user', (value, action) => {
      console.log(`User data ${action}:`, value);
    });
    
    // 批量操作
    const results = storage.batch([
      { type: 'set', key: 'setting1', value: 'value1' },
      { type: 'set', key: 'setting2', value: 'value2' },
      { type: 'get', key: 'setting1' },
      { type: 'remove', key: 'setting2' }
    ]);
    
    console.log('Batch results:', results);
    
    // 获取统计信息
    const stats = storage.getStats();
    console.log('Storage stats:', stats);
    
    // 导出数据
    const exported = storage.export();
    console.log('Exported data:', exported);
    
    // 取消观察
    unsubscribe();
    
    return storage;
  }
}
1.2 存储类型自动选择器
javascript 复制代码
class SmartStorage {
  constructor(options = {}) {
    this.options = {
      memoryLimit: 100, // 内存缓存项数限制
      fallbackOrder: ['memory', 'localStorage', 'sessionStorage', 'cookie'],
      defaultTTL: 24 * 60 * 60 * 1000, // 默认24小时过期
      ...options
    };
    
    this.storages = {
      memory: new Map(),
      localStorage: window.localStorage,
      sessionStorage: window.sessionStorage,
      cookie: this.createCookieHandler()
    };
    
    this.stats = {
      hits: { memory: 0, localStorage: 0, sessionStorage: 0, cookie: 0 },
      misses: 0,
      writes: 0,
      deletes: 0
    };
    
    this.memoryQueue = [];
    this.init();
  }
  
  createCookieHandler() {
    return {
      setItem: (key, value, days = 7) => {
        const expires = new Date(Date.now() + days * 864e5).toUTCString();
        document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}; expires=${expires}; path=/`;
      },
      getItem: (key) => {
        const match = document.cookie.match(new RegExp('(^| )' + key + '=([^;]+)'));
        return match ? decodeURIComponent(match[2]) : null;
      },
      removeItem: (key) => {
        document.cookie = `${key}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
      }
    };
  }
  
  init() {
    // 尝试检测存储可用性
    this.storageAvailable = this.detectStorageAvailability();
    
    // 设置内存缓存清理定时器
    setInterval(() => this.cleanupMemoryCache(), 60000);
  }
  
  detectStorageAvailability() {
    const results = {};
    
    try {
      const testKey = '__storage_test__';
      results.localStorage = (() => {
        try {
          window.localStorage.setItem(testKey, testKey);
          window.localStorage.removeItem(testKey);
          return true;
        } catch (e) {
          return false;
        }
      })();
      
      results.sessionStorage = (() => {
        try {
          window.sessionStorage.setItem(testKey, testKey);
          window.sessionStorage.removeItem(testKey);
          return true;
        } catch (e) {
          return false;
        }
      })();
      
      results.cookie = navigator.cookieEnabled;
      
      return results;
    } catch (e) {
      return {
        localStorage: false,
        sessionStorage: false,
        cookie: false
      };
    }
  }
  
  // 智能设置数据
  async set(key, value, options = {}) {
    const {
      ttl = this.options.defaultTTL,
      priority = 'normal', // 'low', 'normal', 'high', 'critical'
      persist = true,
      compress = false
    } = options;
    
    const storageMeta = {
      timestamp: Date.now(),
      expiry: Date.now() + ttl,
      priority,
      persist,
      compress,
      value
    };
    
    // 总是更新内存缓存
    this.updateMemoryCache(key, storageMeta);
    
    // 根据优先级和持久化选项选择存储后端
    if (persist) {
      await this.persistToStorage(key, storageMeta);
    }
    
    this.stats.writes++;
    return true;
  }
  
  updateMemoryCache(key, meta) {
    // 检查内存限制
    if (this.memoryQueue.length >= this.options.memoryLimit) {
      const oldestKey = this.memoryQueue.shift();
      this.storages.memory.delete(oldestKey);
    }
    
    this.storages.memory.set(key, meta);
    
    // 更新队列顺序
    const existingIndex = this.memoryQueue.indexOf(key);
    if (existingIndex > -1) {
      this.memoryQueue.splice(existingIndex, 1);
    }
    this.memoryQueue.push(key);
  }
  
  async persistToStorage(key, meta) {
    const storageValue = JSON.stringify({
      data: meta.value,
      meta: {
        timestamp: meta.timestamp,
        expiry: meta.expiry,
        priority: meta.priority,
        compress: meta.compress
      }
    });
    
    // 根据优先级选择存储后端
    let storageBackend = 'localStorage';
    
    if (meta.priority === 'critical') {
      // 关键数据存储到多个后端
      if (this.storageAvailable.localStorage) {
        try {
          this.storages.localStorage.setItem(key, storageValue);
        } catch (e) {
          console.warn('localStorage full, trying sessionStorage');
        }
      }
      
      if (this.storageAvailable.sessionStorage) {
        try {
          this.storages.sessionStorage.setItem(key, storageValue);
        } catch (e) {
          console.warn('sessionStorage full, trying cookies');
        }
      }
      
      if (this.storageAvailable.cookie) {
        this.storages.cookie.setItem(key, storageValue, 7); // 7天
      }
    } else if (meta.priority === 'high') {
      storageBackend = this.storageAvailable.localStorage ? 'localStorage' : 
                       this.storageAvailable.sessionStorage ? 'sessionStorage' : 'cookie';
    } else {
      storageBackend = this.options.fallbackOrder.find(backend => 
        this.storageAvailable[backend] !== false
      ) || 'memory';
    }
    
    try {
      if (storageBackend === 'cookie') {
        this.storages.cookie.setItem(key, storageValue, Math.ceil((meta.expiry - Date.now()) / 86400000));
      } else if (storageBackend === 'localStorage' || storageBackend === 'sessionStorage') {
        this.storages[storageBackend].setItem(key, storageValue);
      }
    } catch (error) {
      console.warn(`Failed to persist to ${storageBackend}:`, error);
      
      // 尝试下一个后备存储
      const nextBackend = this.options.fallbackOrder[
        this.options.fallbackOrder.indexOf(storageBackend) + 1
      ];
      if (nextBackend) {
        await this.persistToStorage(key, { ...meta, storageBackend: nextBackend });
      }
    }
  }
  
  // 智能获取数据
  async get(key, options = {}) {
    const { forceFresh = false } = options;
    
    // 首先检查内存缓存
    if (!forceFresh && this.storages.memory.has(key)) {
      const cached = this.storages.memory.get(key);
      
      // 检查是否过期
      if (Date.now() > cached.expiry) {
        this.storages.memory.delete(key);
        this.stats.misses++;
      } else {
        // 更新访问时间
        cached.lastAccessed = Date.now();
        this.stats.hits.memory++;
        
        // 移动到最后(LRU)
        const index = this.memoryQueue.indexOf(key);
        if (index > -1) {
          this.memoryQueue.splice(index, 1);
          this.memoryQueue.push(key);
        }
        
        return cached.value;
      }
    }
    
    // 从持久化存储中查找
    let result = null;
    
    for (const backend of this.options.fallbackOrder) {
      if (backend === 'memory') continue;
      
      try {
        let storedValue = null;
        
        if (backend === 'cookie') {
          storedValue = this.storages.cookie.getItem(key);
        } else if (backend === 'localStorage' || backend === 'sessionStorage') {
          storedValue = this.storages[backend].getItem(key);
        }
        
        if (storedValue) {
          const parsed = JSON.parse(storedValue);
          
          // 检查是否过期
          if (Date.now() > parsed.meta.expiry) {
            this.remove(key); // 删除过期数据
            continue;
          }
          
          result = parsed.data;
          this.stats.hits[backend]++;
          
          // 更新到内存缓存
          this.updateMemoryCache(key, {
            value: result,
            timestamp: parsed.meta.timestamp,
            expiry: parsed.meta.expiry,
            priority: parsed.meta.priority,
            persist: true,
            compress: parsed.meta.compress
          });
          
          break;
        }
      } catch (error) {
        console.warn(`Error reading from ${backend}:`, error);
        continue;
      }
    }
    
    if (result === null) {
      this.stats.misses++;
    }
    
    return result;
  }
  
  // 删除数据
  async remove(key) {
    // 从所有存储后端删除
    this.storages.memory.delete(key);
    
    const index = this.memoryQueue.indexOf(key);
    if (index > -1) {
      this.memoryQueue.splice(index, 1);
    }
    
    if (this.storageAvailable.localStorage) {
      this.storages.localStorage.removeItem(key);
    }
    
    if (this.storageAvailable.sessionStorage) {
      this.storages.sessionStorage.removeItem(key);
    }
    
    if (this.storageAvailable.cookie) {
      this.storages.cookie.removeItem(key);
    }
    
    this.stats.deletes++;
    return true;
  }
  
  // 清理内存缓存
  cleanupMemoryCache() {
    const now = Date.now();
    let cleaned = 0;
    
    for (const [key, meta] of this.storages.memory.entries()) {
      if (now > meta.expiry) {
        this.storages.memory.delete(key);
        cleaned++;
      }
    }
    
    // 如果仍然超过限制,移除最旧的项
    if (this.memoryQueue.length > this.options.memoryLimit) {
      const toRemove = this.memoryQueue.slice(0, this.memoryQueue.length - this.options.memoryLimit);
      toRemove.forEach(key => {
        this.storages.memory.delete(key);
      });
      this.memoryQueue = this.memoryQueue.slice(-this.options.memoryLimit);
      cleaned += toRemove.length;
    }
    
    if (cleaned > 0) {
      console.log(`Cleaned ${cleaned} items from memory cache`);
    }
  }
  
  // 获取缓存统计信息
  getStats() {
    const now = Date.now();
    const memoryItems = Array.from(this.storages.memory.entries());
    
    return {
      ...this.stats,
      memory: {
        items: memoryItems.length,
        hits: this.stats.hits.memory,
        oldest: memoryItems.length > 0 ? 
          Math.round((now - memoryItems[0][1].timestamp) / 1000) : 0,
        newest: memoryItems.length > 0 ? 
          Math.round((now - memoryItems[memoryItems.length - 1][1].timestamp) / 1000) : 0
      },
      localStorage: {
        available: this.storageAvailable.localStorage,
        hits: this.stats.hits.localStorage
      },
      sessionStorage: {
        available: this.storageAvailable.sessionStorage,
        hits: this.stats.hits.sessionStorage
      },
      cookie: {
        available: this.storageAvailable.cookie,
        hits: this.stats.hits.cookie
      }
    };
  }
  
  // 清空所有存储
  async clear() {
    this.storages.memory.clear();
    this.memoryQueue = [];
    
    if (this.storageAvailable.localStorage) {
      this.storages.localStorage.clear();
    }
    
    if (this.storageAvailable.sessionStorage) {
      this.storages.sessionStorage.clear();
    }
    
    // 清除cookie需要特殊处理
    if (this.storageAvailable.cookie) {
      const cookies = document.cookie.split(';');
      for (const cookie of cookies) {
        const eqPos = cookie.indexOf('=');
        const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
        document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
      }
    }
    
    return true;
  }
}

二、IndexedDB 高级封装

2.1 完整的 IndexedDB 包装器
javascript 复制代码
class IndexedDBManager {
  constructor(dbName, version = 1) {
    this.dbName = dbName;
    this.version = version;
    this.db = null;
    this.stores = new Map();
    this.transactions = new Map();
    this.queue = [];
    this.processingQueue = false;
    this.autoIncrementCounters = new Map();
    this.migrationRegistry = new Map();
    
    // 注册事件
    this.events = {
      onUpgradeNeeded: new Set(),
      onSuccess: new Set(),
      onError: new Set(),
      onVersionChange: new Set()
    };
  }
  
  // 注册数据库迁移
  registerMigration(fromVersion, toVersion, migration) {
    const key = `${fromVersion}_${toVersion}`;
    this.migrationRegistry.set(key, migration);
  }
  
  // 初始化数据库
  async init(schema = {}) {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.version);
      
      request.onerror = (event) => {
        console.error('IndexedDB opening error:', event.target.error);
        this.events.onError.forEach(callback => callback(event.target.error));
        reject(event.target.error);
      };
      
      request.onsuccess = (event) => {
        this.db = event.target.result;
        console.log(`IndexedDB ${this.dbName} opened successfully`);
        
        // 监听版本变化
        this.db.onversionchange = (event) => {
          console.log('Database version changed, closing connections');
          this.events.onVersionChange.forEach(callback => callback(event));
          this.db.close();
        };
        
        this.events.onSuccess.forEach(callback => callback(this.db));
        resolve(this.db);
      };
      
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        const oldVersion = event.oldVersion;
        const newVersion = event.newVersion;
        
        console.log(`Upgrading database from ${oldVersion} to ${newVersion}`);
        
        // 执行注册的迁移
        this.executeMigrations(db, oldVersion, newVersion);
        
        // 应用新模式
        this.applySchema(db, schema);
        
        this.events.onUpgradeNeeded.forEach(callback => callback(event));
      };
    });
  }
  
  // 执行迁移
  executeMigrations(db, oldVersion, newVersion) {
    for (let version = oldVersion; version < newVersion; version++) {
      const migrationKey = `${version}_${version + 1}`;
      const migration = this.migrationRegistry.get(migrationKey);
      
      if (migration) {
        console.log(`Executing migration ${migrationKey}`);
        try {
          migration(db, version, version + 1);
        } catch (error) {
          console.error(`Migration ${migrationKey} failed:`, error);
          throw error;
        }
      }
    }
  }
  
  // 应用数据库模式
  applySchema(db, schema) {
    Object.entries(schema).forEach(([storeName, storeConfig]) => {
      if (!db.objectStoreNames.contains(storeName)) {
        console.log(`Creating object store: ${storeName}`);
        
        const { keyPath = 'id', autoIncrement = true, indices = [] } = storeConfig;
        const store = db.createObjectStore(storeName, { keyPath, autoIncrement });
        
        // 创建索引
        indices.forEach(indexConfig => {
          const { name, keyPath, unique = false, multiEntry = false } = indexConfig;
          store.createIndex(name, keyPath, { unique, multiEntry });
        });
        
        this.stores.set(storeName, { ...storeConfig, store });
      } else {
        // 更新现有存储
        const transaction = db.transaction([storeName], 'readwrite');
        const store = transaction.objectStore(storeName);
        
        const existingIndices = Array.from(store.indexNames);
        const { indices = [] } = storeConfig;
        
        // 添加新索引
        indices.forEach(indexConfig => {
          if (!existingIndices.includes(indexConfig.name)) {
            console.log(`Creating index ${indexConfig.name} on ${storeName}`);
            store.createIndex(
              indexConfig.name,
              indexConfig.keyPath,
              { unique: indexConfig.unique || false, multiEntry: indexConfig.multiEntry || false }
            );
          }
        });
      }
    });
  }
  
  // 添加数据
  async add(storeName, data) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore(storeName);
      
      // 生成ID(如果需要)
      let processedData = { ...data };
      const storeConfig = this.stores.get(storeName);
      
      if (storeConfig.autoIncrement && !processedData[storeConfig.keyPath]) {
        const counter = this.getAutoIncrementCounter(storeName);
        processedData[storeConfig.keyPath] = counter;
      }
      
      const request = store.add(processedData);
      
      request.onsuccess = (event) => {
        resolve({ id: event.target.result, data: processedData });
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 批量添加数据
  async addBulk(storeName, items) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore(storeName);
      const results = [];
      
      items.forEach((item, index) => {
        let processedItem = { ...item };
        const storeConfig = this.stores.get(storeName);
        
        if (storeConfig.autoIncrement && !processedItem[storeConfig.keyPath]) {
          const counter = this.getAutoIncrementCounter(storeName, index);
          processedItem[storeConfig.keyPath] = counter;
        }
        
        const request = store.add(processedItem);
        
        request.onsuccess = (event) => {
          results.push({ id: event.target.result, data: processedItem });
          
          if (results.length === items.length) {
            resolve(results);
          }
        };
        
        request.onerror = (event) => {
          reject(event.target.error);
        };
      });
    });
  }
  
  // 获取数据
  async get(storeName, key) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readonly');
      const store = transaction.objectStore(storeName);
      const request = store.get(key);
      
      request.onsuccess = (event) => {
        resolve(event.target.result);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 通过索引查询
  async getByIndex(storeName, indexName, value) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readonly');
      const store = transaction.objectStore(storeName);
      const index = store.index(indexName);
      const request = index.get(value);
      
      request.onsuccess = (event) => {
        resolve(event.target.result);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 查询所有数据
  async getAll(storeName, query = null, count = null) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readonly');
      const store = transaction.objectStore(storeName);
      let request;
      
      if (query) {
        const range = this.createRange(query);
        request = store.getAll(range, count);
      } else {
        request = store.getAll();
      }
      
      request.onsuccess = (event) => {
        resolve(event.target.result);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 创建IDBKeyRange
  createRange(query) {
    if (typeof query === 'object') {
      if (query.lower && query.upper) {
        return IDBKeyRange.bound(query.lower, query.upper, query.lowerOpen, query.upperOpen);
      } else if (query.lower) {
        return IDBKeyRange.lowerBound(query.lower, query.open);
      } else if (query.upper) {
        return IDBKeyRange.upperBound(query.upper, query.open);
      } else if (query.only) {
        return IDBKeyRange.only(query.only);
      }
    }
    return IDBKeyRange.only(query);
  }
  
  // 更新数据
  async update(storeName, key, updates) {
    return new Promise(async (resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      try {
        // 先获取现有数据
        const existing = await this.get(storeName, key);
        if (!existing) {
          reject(new Error(`Record with key ${key} not found`));
          return;
        }
        
        const transaction = this.db.transaction([storeName], 'readwrite');
        const store = transaction.objectStore(storeName);
        const updatedData = { ...existing, ...updates, _updatedAt: Date.now() };
        
        const request = store.put(updatedData);
        
        request.onsuccess = (event) => {
          resolve(updatedData);
        };
        
        request.onerror = (event) => {
          reject(event.target.error);
        };
      } catch (error) {
        reject(error);
      }
    });
  }
  
  // 删除数据
  async delete(storeName, key) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore(storeName);
      const request = store.delete(key);
      
      request.onsuccess = (event) => {
        resolve(true);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 清空存储
  async clearStore(storeName) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readwrite');
      const store = transaction.objectStore(storeName);
      const request = store.clear();
      
      request.onsuccess = (event) => {
        resolve(true);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 计数
  async count(storeName, query = null) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const transaction = this.db.transaction([storeName], 'readonly');
      const store = transaction.objectStore(storeName);
      let request;
      
      if (query) {
        const range = this.createRange(query);
        request = store.count(range);
      } else {
        request = store.count();
      }
      
      request.onsuccess = (event) => {
        resolve(event.target.result);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 游标遍历
  async cursor(storeName, callback, options = {}) {
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      const { direction = 'next', range = null, indexName = null } = options;
      const transaction = this.db.transaction([storeName], 'readonly');
      const store = transaction.objectStore(storeName);
      let source = store;
      
      if (indexName) {
        source = store.index(indexName);
      }
      
      const rangeObj = range ? this.createRange(range) : null;
      const request = source.openCursor(rangeObj, direction);
      const results = [];
      
      request.onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
          const shouldContinue = callback(cursor.value, cursor);
          results.push(cursor.value);
          
          if (shouldContinue !== false) {
            cursor.continue();
          } else {
            resolve(results);
          }
        } else {
          resolve(results);
        }
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
    });
  }
  
  // 批量操作事务
  async transaction(operations) {
    return new Promise(async (resolve, reject) => {
      if (!this.db) {
        reject(new Error('Database not initialized'));
        return;
      }
      
      // 获取所有涉及的存储名称
      const storeNames = [...new Set(operations.map(op => op.store))];
      
      const transaction = this.db.transaction(storeNames, 'readwrite');
      const results = [];
      let errorOccurred = false;
      
      transaction.onerror = (event) => {
        errorOccurred = true;
        reject(event.target.error);
      };
      
      transaction.oncomplete = (event) => {
        if (!errorOccurred) {
          resolve(results);
        }
      };
      
      for (const operation of operations) {
        try {
          const { store, type, data, key, updates } = operation;
          const objectStore = transaction.objectStore(store);
          let request;
          
          switch (type) {
            case 'add':
              request = objectStore.add(data);
              break;
            case 'put':
              request = objectStore.put(data);
              break;
            case 'get':
              request = objectStore.get(key);
              break;
            case 'delete':
              request = objectStore.delete(key);
              break;
            case 'update':
              // 对于更新,需要先获取再更新
              const getRequest = objectStore.get(key);
              getRequest.onsuccess = (event) => {
                const existing = event.target.result;
                if (existing) {
                  const updated = { ...existing, ...updates };
                  objectStore.put(updated);
                }
              };
              continue;
            default:
              throw new Error(`Unknown operation type: ${type}`);
          }
          
          request.onsuccess = (event) => {
            results.push({
              store,
              type,
              result: event.target.result,
              success: true
            });
          };
          
          request.onerror = (event) => {
            results.push({
              store,
              type,
              error: event.target.error,
              success: false
            });
          };
        } catch (error) {
          results.push({
            store: operation.store,
            type: operation.type,
            error,
            success: false
          });
        }
      }
    });
  }
  
  // 获取自增计数器
  getAutoIncrementCounter(storeName, offset = 0) {
    if (!this.autoIncrementCounters.has(storeName)) {
      this.autoIncrementCounters.set(storeName, 1);
    }
    
    const current = this.autoIncrementCounters.get(storeName);
    this.autoIncrementCounters.set(storeName, current + 1 + offset);
    return current + offset;
  }
  
  // 数据库备份
  async backup() {
    if (!this.db) {
      throw new Error('Database not initialized');
    }
    
    const backup = {
      dbName: this.dbName,
      version: this.version,
      timestamp: Date.now(),
      stores: {}
    };
    
    const storeNames = Array.from(this.db.objectStoreNames);
    
    for (const storeName of storeNames) {
      const data = await this.getAll(storeName);
      backup.stores[storeName] = data;
    }
    
    return backup;
  }
  
  // 从备份恢复
  async restore(backup) {
    if (!this.db) {
      throw new Error('Database not initialized');
    }
    
    // 清空现有数据
    const storeNames = Array.from(this.db.objectStoreNames);
    for (const storeName of storeNames) {
      await this.clearStore(storeName);
    }
    
    // 恢复数据
    for (const [storeName, data] of Object.entries(backup.stores)) {
      if (this.db.objectStoreNames.contains(storeName)) {
        await this.addBulk(storeName, data);
      }
    }
    
    return true;
  }
  
  // 获取数据库信息
  async getInfo() {
    if (!this.db) {
      throw new Error('Database not initialized');
    }
    
    const info = {
      name: this.db.name,
      version: this.db.version,
      objectStores: [],
      estimatedSize: 0
    };
    
    const storeNames = Array.from(this.db.objectStoreNames);
    
    for (const storeName of storeNames) {
      const count = await this.count(storeName);
      info.objectStores.push({
        name: storeName,
        count
      });
    }
    
    // 尝试估算大小(通过读取所有数据)
    try {
      let totalSize = 0;
      for (const storeName of storeNames) {
        const allData = await this.getAll(storeName);
        const jsonString = JSON.stringify(allData);
        totalSize += new Blob([jsonString]).size;
      }
      info.estimatedSize = totalSize;
    } catch (error) {
      console.warn('Could not estimate database size:', error);
    }
    
    return info;
  }
  
  // 关闭数据库
  close() {
    if (this.db) {
      this.db.close();
      this.db = null;
      console.log(`Database ${this.dbName} closed`);
    }
  }
  
  // 删除数据库
  static async deleteDatabase(dbName) {
    return new Promise((resolve, reject) => {
      const request = indexedDB.deleteDatabase(dbName);
      
      request.onsuccess = () => {
        console.log(`Database ${dbName} deleted`);
        resolve(true);
      };
      
      request.onerror = (event) => {
        reject(event.target.error);
      };
      
      request.onblocked = () => {
        console.warn(`Database ${dbName} deletion blocked`);
        reject(new Error('Database deletion blocked by open connections'));
      };
    });
  }
}

// 使用示例
class IndexedDBExample {
  static async demonstrate() {
    // 创建数据库管理器
    const dbManager = new IndexedDBManager('MyAppDB', 2);
    
    // 注册迁移
    dbManager.registerMigration(1, 2, (db, oldVersion, newVersion) => {
      // 从版本1迁移到版本2
      if (!db.objectStoreNames.contains('users')) {
        const store = db.createObjectStore('users', { keyPath: 'id', autoIncrement: true });
        store.createIndex('email', 'email', { unique: true });
      }
    });
    
    // 定义数据库模式
    const schema = {
      users: {
        keyPath: 'id',
        autoIncrement: true,
        indices: [
          { name: 'email', keyPath: 'email', unique: true },
          { name: 'name', keyPath: 'name', unique: false }
        ]
      },
      products: {
        keyPath: 'sku',
        autoIncrement: false,
        indices: [
          { name: 'category', keyPath: 'category', unique: false },
          { name: 'price', keyPath: 'price', unique: false }
        ]
      }
    };
    
    // 初始化数据库
    await dbManager.init(schema);
    
    // 添加用户
    const user = await dbManager.add('users', {
      name: 'John Doe',
      email: 'john@example.com',
      age: 30
    });
    
    console.log('Added user:', user);
    
    // 批量添加产品
    const products = await dbManager.addBulk('products', [
      { sku: 'P001', name: 'Product 1', category: 'electronics', price: 99.99 },
      { sku: 'P002', name: 'Product 2', category: 'clothing', price: 49.99 },
      { sku: 'P003', name: 'Product 3', category: 'electronics', price: 199.99 }
    ]);
    
    console.log('Added products:', products);
    
    // 通过索引查询
    const userByEmail = await dbManager.getByIndex('users', 'email', 'john@example.com');
    console.log('User by email:', userByEmail);
    
    // 游标遍历
    const expensiveProducts = await dbManager.cursor('products', (product, cursor) => {
      console.log('Product:', product);
      // 返回false停止遍历
      return product.price < 150;
    }, { indexName: 'price', direction: 'next' });
    
    // 获取数据库信息
    const info = await dbManager.getInfo();
    console.log('Database info:', info);
    
    // 备份数据库
    const backup = await dbManager.backup();
    console.log('Backup created:', backup);
    
    return dbManager;
  }
}
2.2 IndexedDB 查询构建器
javascript 复制代码
class IndexedDBQueryBuilder {
  constructor(dbManager, storeName) {
    this.dbManager = dbManager;
    this.storeName = storeName;
    this.query = {
      filters: [],
      sort: null,
      limit: null,
      offset: 0,
      indexes: []
    };
  }
  
  // 等于条件
  where(field, value) {
    this.query.filters.push({ field, operator: '=', value });
    return this;
  }
  
  // 不等于条件
  whereNot(field, value) {
    this.query.filters.push({ field, operator: '!=', value });
    return this;
  }
  
  // 大于条件
  whereGreaterThan(field, value) {
    this.query.filters.push({ field, operator: '>', value });
    return this;
  }
  
  // 小于条件
  whereLessThan(field, value) {
    this.query.filters.push({ field, operator: '<', value });
    return this;
  }
  
  // 大于等于条件
  whereGreaterOrEqual(field, value) {
    this.query.filters.push({ field, operator: '>=', value });
    return this;
  }
  
  // 小于等于条件
  whereLessOrEqual(field, value) {
    this.query.filters.push({ field, operator: '<=', value });
    return this;
  }
  
  // 包含条件
  whereIn(field, values) {
    this.query.filters.push({ field, operator: 'in', value: values });
    return this;
  }
  
  // 范围条件
  whereBetween(field, min, max) {
    this.query.filters.push({ field, operator: 'between', value: { min, max } });
    return this;
  }
  
  // 字符串包含
  whereContains(field, substring) {
    this.query.filters.push({ field, operator: 'contains', value: substring });
    return this;
  }
  
  // 字符串开头
  whereStartsWith(field, prefix) {
    this.query.filters.push({ field, operator: 'startsWith', value: prefix });
    return this;
  }
  
  // 字符串结尾
  whereEndsWith(field, suffix) {
    this.query.filters.push({ field, operator: 'endsWith', value: suffix });
    return this;
  }
  
  // 排序
  orderBy(field, direction = 'asc') {
    this.query.sort = { field, direction };
    return this;
  }
  
  // 限制数量
  limit(count) {
    this.query.limit = count;
    return this;
  }
  
  // 偏移量
  offset(count) {
    this.query.offset = count;
    return this;
  }
  
  // 使用索引
  useIndex(indexName) {
    this.query.indexes.push(indexName);
    return this;
  }
  
  // 执行查询
  async execute() {
    if (this.query.filters.length === 0) {
      // 无过滤器,直接获取所有数据
      return this.dbManager.getAll(this.storeName, null, this.query.limit);
    }
    
    // 使用游标进行复杂查询
    return new Promise((resolve, reject) => {
      this.dbManager.cursor(this.storeName, (record, cursor) => {
        const results = [];
        let count = 0;
        let skipped = 0;
        
        const processRecord = (record) => {
          // 检查偏移量
          if (skipped < this.query.offset) {
            skipped++;
            return false;
          }
          
          // 检查限制
          if (this.query.limit && count >= this.query.limit) {
            return false;
          }
          
          // 应用过滤器
          if (this.matchesFilters(record)) {
            results.push(record);
            count++;
          }
          
          return true;
        };
        
        if (processRecord(record)) {
          cursor.continue();
        } else {
          resolve(results);
        }
      }, {
        indexName: this.query.indexes[0] || null,
        direction: this.query.sort?.direction === 'desc' ? 'prev' : 'next'
      }).then(resolve).catch(reject);
    });
  }
  
  // 检查记录是否匹配所有过滤器
  matchesFilters(record) {
    return this.query.filters.every(filter => {
      const value = record[filter.field];
      
      switch (filter.operator) {
        case '=':
          return value === filter.value;
        case '!=':
          return value !== filter.value;
        case '>':
          return value > filter.value;
        case '<':
          return value < filter.value;
        case '>=':
          return value >= filter.value;
        case '<=':
          return value <= filter.value;
        case 'in':
          return Array.isArray(filter.value) && filter.value.includes(value);
        case 'between':
          return value >= filter.value.min && value <= filter.value.max;
        case 'contains':
          return typeof value === 'string' && value.includes(filter.value);
        case 'startsWith':
          return typeof value === 'string' && value.startsWith(filter.value);
        case 'endsWith':
          return typeof value === 'string' && value.endsWith(filter.value);
        default:
          return true;
      }
    });
  }
  
  // 计数
  async count() {
    const results = await this.execute();
    return results.length;
  }
  
  // 获取第一条记录
  async first() {
    const results = await this.limit(1).execute();
    return results[0] || null;
  }
  
  // 获取最后一条记录
  async last() {
    const results = await this.execute();
    return results[results.length - 1] || null;
  }
  
  // 检查是否存在
  async exists() {
    const result = await this.first();
    return result !== null;
  }
  
  // 更新匹配的记录
  async update(updates) {
    const results = await this.execute();
    const updatePromises = results.map(record => {
      const key = record.id || record[this.dbManager.stores.get(this.storeName).keyPath];
      return this.dbManager.update(this.storeName, key, updates);
    });
    
    return Promise.all(updatePromises);
  }
  
  // 删除匹配的记录
  async delete() {
    const results = await this.execute();
    const deletePromises = results.map(record => {
      const key = record.id || record[this.dbManager.stores.get(this.storeName).keyPath];
      return this.dbManager.delete(this.storeName, key);
    });
    
    return Promise.all(deletePromises);
  }
  
  // 分页查询
  async paginate(page = 1, perPage = 20) {
    const offset = (page - 1) * perPage;
    const results = await this.offset(offset).limit(perPage).execute();
    const total = await this.count();
    
    return {
      data: results,
      pagination: {
        page,
        perPage,
        total,
        totalPages: Math.ceil(total / perPage),
        hasNext: page * perPage < total,
        hasPrev: page > 1
      }
    };
  }
}

// 使用示例
class QueryBuilderExample {
  static async demonstrate(dbManager) {
    const queryBuilder = new IndexedDBQueryBuilder(dbManager, 'products');
    
    // 复杂查询
    const results = await queryBuilder
      .where('category', 'electronics')
      .whereGreaterThan('price', 50)
      .whereLessThan('price', 200)
      .orderBy('price', 'desc')
      .limit(10)
      .execute();
    
    console.log('Query results:', results);
    
    // 分页查询
    const page = await queryBuilder
      .where('category', 'electronics')
      .paginate(1, 5);
    
    console.log('Pagination:', page);
    
    return results;
  }
}

三、Cookie 操作库完整实现

javascript 复制代码
class CookieManager {
  constructor(options = {}) {
    this.defaults = {
      path: '/',
      domain: window.location.hostname,
      secure: window.location.protocol === 'https:',
      sameSite: 'Lax',
      expires: 7, // 默认7天
      ...options
    };
    
    this.observers = new Map();
    this.encryptionEnabled = false;
    this.compressionEnabled = false;
    
    // 监听 cookie 变化
    this.setupMutationObserver();
  }
  
  // 设置 Cookie
  set(name, value, options = {}) {
    const config = { ...this.defaults, ...options };
    
    let cookieValue = value;
    
    // 序列化非字符串值
    if (typeof value !== 'string') {
      cookieValue = JSON.stringify(value);
    }
    
    // 加密
    if (config.encrypt && this.encryptionEnabled) {
      cookieValue = this.encrypt(cookieValue, config.encryptionKey);
    }
    
    // 压缩
    if (config.compress && this.compressionEnabled && cookieValue.length > 100) {
      cookieValue = this.compress(cookieValue);
    }
    
    // 构建 cookie 字符串
    let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(cookieValue)}`;
    
    // 添加过期时间
    if (config.expires) {
      let expires = config.expires;
      
      if (typeof expires === 'number') {
        const date = new Date();
        date.setTime(date.getTime() + expires * 24 * 60 * 60 * 1000);
        expires = date.toUTCString();
      } else if (expires instanceof Date) {
        expires = expires.toUTCString();
      }
      
      cookieString += `; expires=${expires}`;
    }
    
    // 添加路径
    if (config.path) {
      cookieString += `; path=${config.path}`;
    }
    
    // 添加域名
    if (config.domain) {
      cookieString += `; domain=${config.domain}`;
    }
    
    // 添加安全标志
    if (config.secure) {
      cookieString += '; secure';
    }
    
    // 添加 SameSite
    if (config.sameSite) {
      cookieString += `; samesite=${config.sameSite}`;
    }
    
    // 设置 cookie
    document.cookie = cookieString;
    
    // 通知观察者
    this.notifyObservers(name, value, 'set');
    
    return true;
  }
  
  // 获取 Cookie
  get(name, defaultValue = null) {
    const cookies = this.getAll();
    
    if (!(name in cookies)) {
      return defaultValue;
    }
    
    let value = cookies[name];
    
    // 解压缩
    if (this.isCompressed(value)) {
      value = this.decompress(value);
    }
    
    // 解密
    if (this.isEncrypted(value)) {
      value = this.decrypt(value);
    }
    
    // 尝试解析 JSON
    try {
      return JSON.parse(value);
    } catch {
      return value;
    }
  }
  
  // 获取所有 Cookie
  getAll() {
    const cookies = {};
    
    if (!document.cookie) {
      return cookies;
    }
    
    document.cookie.split(';').forEach(cookie => {
      const [name, ...valueParts] = cookie.trim().split('=');
      const value = valueParts.join('='); // 处理值中包含等号的情况
      
      try {
        cookies[decodeURIComponent(name)] = decodeURIComponent(value);
      } catch {
        cookies[name] = value;
      }
    });
    
    return cookies;
  }
  
  // 删除 Cookie
  remove(name, options = {}) {
    const config = {
      path: this.defaults.path,
      domain: this.defaults.domain,
      ...options
    };
    
    // 设置过期时间为过去的时间
    this.set(name, '', {
      ...config,
      expires: new Date(0)
    });
    
    // 通知观察者
    this.notifyObservers(name, null, 'remove');
    
    return true;
  }
  
  // 检查 Cookie 是否存在
  has(name) {
    return name in this.getAll();
  }
  
  // 启用加密
  enableEncryption(encryptionKey) {
    if (typeof window.crypto === 'undefined') {
      console.warn('Web Crypto API not available, encryption disabled');
      return false;
    }
    
    this.encryptionEnabled = true;
    this.encryptionKey = encryptionKey;
    return true;
  }
  
  // 启用压缩
  enableCompression() {
    this.compressionEnabled = true;
    return true;
  }
  
  // 加密数据
  encrypt(text, key = this.encryptionKey) {
    if (!this.encryptionEnabled) return text;
    
    try {
      // 简单的 XOR 加密(实际项目中应使用更安全的算法)
      let result = '';
      for (let i = 0; i < text.length; i++) {
        const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
        result += String.fromCharCode(charCode);
      }
      
      return `encrypted:${btoa(result)}`;
    } catch (error) {
      console.error('Encryption failed:', error);
      return text;
    }
  }
  
  // 解密数据
  decrypt(text, key = this.encryptionKey) {
    if (!text.startsWith('encrypted:')) return text;
    
    try {
      const encrypted = atob(text.slice(10));
      let result = '';
      
      for (let i = 0; i < encrypted.length; i++) {
        const charCode = encrypted.charCodeAt(i) ^ key.charCodeAt(i % key.length);
        result += String.fromCharCode(charCode);
      }
      
      return result;
    } catch (error) {
      console.error('Decryption failed:', error);
      return text;
    }
  }
  
  // 判断是否加密
  isEncrypted(text) {
    return text.startsWith('encrypted:');
  }
  
  // 压缩数据
  compress(text) {
    if (!this.compressionEnabled) return text;
    
    try {
      // 简单的压缩(实际项目中可使用 pako 等库)
      const compressed = btoa(encodeURIComponent(text).replace(/%[0-9A-F]{2}/g, ''));
      return `compressed:${compressed}`;
    } catch (error) {
      console.error('Compression failed:', error);
      return text;
    }
  }
  
  // 解压缩数据
  decompress(text) {
    if (!text.startsWith('compressed:')) return text;
    
    try {
      const compressed = text.slice(11);
      return decodeURIComponent(atob(compressed));
    } catch (error) {
      console.error('Decompression failed:', error);
      return text;
    }
  }
  
  // 判断是否压缩
  isCompressed(text) {
    return text.startsWith('compressed:');
  }
  
  // 添加观察者
  observe(name, callback) {
    if (!this.observers.has(name)) {
      this.observers.set(name, new Set());
    }
    
    this.observers.get(name).add(callback);
    
    // 返回取消观察的函数
    return () => {
      const observers = this.observers.get(name);
      if (observers) {
        observers.delete(callback);
        if (observers.size === 0) {
          this.observers.delete(name);
        }
      }
    };
  }
  
  // 通知观察者
  notifyObservers(name, value, action) {
    const observers = this.observers.get(name);
    if (observers) {
      observers.forEach(callback => {
        callback(value, action, name);
      });
    }
    
    // 通知全局观察者
    const globalObservers = this.observers.get('*');
    if (globalObservers) {
      globalObservers.forEach(callback => {
        callback(value, action, name);
      });
    }
  }
  
  // 设置 MutationObserver 监听 cookie 变化
  setupMutationObserver() {
    // 由于 cookie 变化不会触发 DOM 事件,我们需要轮询检查变化
    this.lastCookieString = document.cookie;
    
    this.pollingInterval = setInterval(() => {
      const currentCookieString = document.cookie;
      
      if (currentCookieString !== this.lastCookieString) {
        this.detectCookieChanges(this.lastCookieString, currentCookieString);
        this.lastCookieString = currentCookieString;
      }
    }, 1000); // 每秒检查一次
  }
  
  // 检测 cookie 变化
  detectCookieChanges(oldCookieString, newCookieString) {
    const oldCookies = this.parseCookieString(oldCookieString);
    const newCookies = this.parseCookieString(newCookieString);
    
    // 检测新增或修改的 cookie
    Object.keys(newCookies).forEach(name => {
      if (!oldCookies[name] || oldCookies[name] !== newCookies[name]) {
        this.notifyObservers(name, newCookies[name], oldCookies[name] ? 'update' : 'set');
      }
    });
    
    // 检测删除的 cookie
    Object.keys(oldCookies).forEach(name => {
      if (!newCookies[name]) {
        this.notifyObservers(name, null, 'remove');
      }
    });
  }
  
  // 解析 cookie 字符串
  parseCookieString(cookieString) {
    const cookies = {};
    
    if (!cookieString) return cookies;
    
    cookieString.split(';').forEach(cookie => {
      const [name, ...valueParts] = cookie.trim().split('=');
      const value = valueParts.join('=');
      
      if (name) {
        try {
          cookies[decodeURIComponent(name)] = decodeURIComponent(value);
        } catch {
          cookies[name] = value;
        }
      }
    });
    
    return cookies;
  }
  
  // 批量设置 cookie
  batchSet(cookies, commonOptions = {}) {
    const results = {};
    
    Object.entries(cookies).forEach(([name, value]) => {
      let options = commonOptions;
      let actualValue = value;
      
      // 如果值是对象,可能包含选项
      if (value && typeof value === 'object' && !Array.isArray(value)) {
        if (value.value !== undefined) {
          actualValue = value.value;
          options = { ...commonOptions, ...value.options };
        }
      }
      
      results[name] = this.set(name, actualValue, options);
    });
    
    return results;
  }
  
  // 获取 cookie 大小信息
  getStats() {
    const cookies = this.getAll();
    let totalSize = 0;
    
    Object.entries(cookies).forEach(([name, value]) => {
      // 每个字符在 cookie 中通常占用 1-4 字节,这里估算为 2 字节
      totalSize += (name.length + value.length) * 2;
    });
    
    return {
      count: Object.keys(cookies).length,
      totalSize,
      estimatedRemaining: 4096 - totalSize, // cookie 通常有 4KB 限制
      usagePercentage: (totalSize / 4096) * 100
    };
  }
  
  // 导出所有 cookie
  export() {
    const cookies = this.getAll();
    const exported = {};
    
    Object.entries(cookies).forEach(([name, value]) => {
      exported[name] = value;
    });
    
    return {
      timestamp: Date.now(),
      count: Object.keys(cookies).length,
      cookies: exported
    };
  }
  
  // 从备份导入 cookie
  import(backup) {
    if (!backup || !backup.cookies) {
      throw new Error('Invalid backup data');
    }
    
    Object.entries(backup.cookies).forEach(([name, value]) => {
      this.set(name, value);
    });
    
    return true;
  }
  
  // 销毁实例
  destroy() {
    if (this.pollingInterval) {
      clearInterval(this.pollingInterval);
    }
    this.observers.clear();
  }
}

// 使用示例
class CookieExample {
  static demonstrate() {
    // 创建 cookie 管理器
    const cookieManager = new CookieManager({
      path: '/',
      expires: 30, // 30 天
      sameSite: 'Strict'
    });
    
    // 启用加密
    cookieManager.enableEncryption('my-secret-key');
    
    // 启用压缩
    cookieManager.enableCompression();
    
    // 设置 cookie
    cookieManager.set('user', {
      id: 123,
      name: 'John Doe',
      preferences: { theme: 'dark', language: 'en' }
    }, { encrypt: true });
    
    cookieManager.set('session_token', 'abc123def456', {
      secure: true,
      expires: 1 // 1 天
    });
    
    // 批量设置
    cookieManager.batchSet({
      'theme': 'dark',
      'language': 'en-US',
      'notifications': true
    }, { expires: 7 });
    
    // 获取 cookie
    const user = cookieManager.get('user');
    const theme = cookieManager.get('theme', 'light');
    
    console.log('User:', user);
    console.log('Theme:', theme);
    
    // 观察 cookie 变化
    const unsubscribe = cookieManager.observe('theme', (value, action) => {
      console.log(`Theme cookie ${action}:`, value);
    });
    
    // 获取统计信息
    const stats = cookieManager.getStats();
    console.log('Cookie stats:', stats);
    
    // 导出所有 cookie
    const backup = cookieManager.export();
    console.log('Cookie backup:', backup);
    
    // 取消观察
    unsubscribe();
    
    return cookieManager;
  }
}
javascript 复制代码
class CrossDomainCookieManager {
  constructor() {
    this.iframe = null;
    this.messageHandlers = new Map();
    this.ready = false;
    this.targetOrigin = '*';
    
    // 设置消息监听
    window.addEventListener('message', this.handleMessage.bind(this), false);
  }
  
  // 初始化跨域通信
  init(targetDomain, options = {}) {
    return new Promise((resolve, reject) => {
      this.targetOrigin = targetDomain;
      
      // 创建隐藏的 iframe
      this.iframe = document.createElement('iframe');
      this.iframe.style.display = 'none';
      this.iframe.src = `${targetDomain}/cookie-proxy.html`;
      
      this.iframe.onload = () => {
        this.ready = true;
        console.log('Cookie proxy iframe loaded');
        resolve(this);
      };
      
      this.iframe.onerror = (error) => {
        reject(new Error('Failed to load cookie proxy iframe'));
      };
      
      document.body.appendChild(this.iframe);
    });
  }
  
  // 处理消息
  handleMessage(event) {
    // 验证来源
    if (this.targetOrigin !== '*' && event.origin !== this.targetOrigin) {
      return;
    }
    
    const { type, id, data, error } = event.data;
    
    if (!type || !id) return;
    
    const handler = this.messageHandlers.get(id);
    if (handler) {
      if (error) {
        handler.reject(new Error(error));
      } else {
        handler.resolve(data);
      }
      this.messageHandlers.delete(id);
    }
  }
  
  // 发送消息到 iframe
  sendMessage(type, data) {
    return new Promise((resolve, reject) => {
      if (!this.ready || !this.iframe) {
        reject(new Error('Cookie proxy not ready'));
        return;
      }
      
      const id = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      
      this.messageHandlers.set(id, { resolve, reject });
      
      this.iframe.contentWindow.postMessage({
        type,
        id,
        data
      }, this.targetOrigin);
      
      // 设置超时
      setTimeout(() => {
        if (this.messageHandlers.has(id)) {
          this.messageHandlers.delete(id);
          reject(new Error('Request timeout'));
        }
      }, 5000);
    });
  }
  
  // 设置跨域 cookie
  async setCookie(name, value, options = {}) {
    return this.sendMessage('SET_COOKIE', { name, value, options });
  }
  
  // 获取跨域 cookie
  async getCookie(name, defaultValue = null) {
    try {
      const value = await this.sendMessage('GET_COOKIE', { name });
      return value || defaultValue;
    } catch (error) {
      console.error('Failed to get cross-domain cookie:', error);
      return defaultValue;
    }
  }
  
  // 删除跨域 cookie
  async removeCookie(name, options = {}) {
    return this.sendMessage('REMOVE_COOKIE', { name, options });
  }
  
  // 获取所有跨域 cookie
  async getAllCookies() {
    return this.sendMessage('GET_ALL_COOKIES', {});
  }
  
  // 销毁
  destroy() {
    if (this.iframe) {
      document.body.removeChild(this.iframe);
      this.iframe = null;
    }
    
    window.removeEventListener('message', this.handleMessage);
    this.messageHandlers.clear();
    this.ready = false;
  }
}

// Cookie 代理页面代码(需要部署在目标域)
class CookieProxy {
  constructor() {
    this.initMessageHandler();
  }
  
  initMessageHandler() {
    window.addEventListener('message', async (event) => {
      const { type, id, data } = event.data;
      
      if (!type || !id) return;
      
      try {
        let result;
        
        switch (type) {
          case 'SET_COOKIE':
            result = this.setCookie(data.name, data.value, data.options);
            break;
          case 'GET_COOKIE':
            result = this.getCookie(data.name);
            break;
          case 'REMOVE_COOKIE':
            result = this.removeCookie(data.name, data.options);
            break;
          case 'GET_ALL_COOKIES':
            result = this.getAllCookies();
            break;
          default:
            throw new Error(`Unknown message type: ${type}`);
        }
        
        // 发送响应
        event.source.postMessage({
          type: 'RESPONSE',
          id,
          data: await result
        }, event.origin);
      } catch (error) {
        event.source.postMessage({
          type: 'ERROR',
          id,
          error: error.message
        }, event.origin);
      }
    }, false);
  }
  
  // 设置 cookie(本地)
  setCookie(name, value, options = {}) {
    const cookieManager = new CookieManager();
    return cookieManager.set(name, value, options);
  }
  
  // 获取 cookie(本地)
  getCookie(name) {
    const cookieManager = new CookieManager();
    return cookieManager.get(name);
  }
  
  // 删除 cookie(本地)
  removeCookie(name, options = {}) {
    const cookieManager = new CookieManager();
    return cookieManager.remove(name, options);
  }
  
  // 获取所有 cookie(本地)
  getAllCookies() {
    const cookieManager = new CookieManager();
    return cookieManager.getAll();
  }
}

// 使用示例
class CrossDomainExample {
  static async demonstrate() {
    // 主域中的代码
    const crossDomainManager = new CrossDomainCookieManager();
    
    try {
      // 初始化连接(假设子域为 https://api.example.com)
      await crossDomainManager.init('https://api.example.com');
      
      // 在子域中设置 cookie
      await crossDomainManager.setCookie('api_token', 'secret_token_123', {
        expires: 7,
        secure: true
      });
      
      // 从子域获取 cookie
      const token = await crossDomainManager.getCookie('api_token');
      console.log('API token from subdomain:', token);
      
      // 获取子域中的所有 cookie
      const allCookies = await crossDomainManager.getAllCookies();
      console.log('All cookies from subdomain:', allCookies);
      
      return crossDomainManager;
    } catch (error) {
      console.error('Cross-domain cookie operation failed:', error);
      return null;
    }
  }
}

四、存储安全性与最佳实践

4.1 安全存储包装器
javascript 复制代码
class SecureStorage {
  constructor(options = {}) {
    this.options = {
      encryptionAlgorithm: 'AES-GCM',
      keyDerivationIterations: 100000,
      storageBackend: 'auto', // 'localStorage', 'sessionStorage', 'indexedDB', 'auto'
      ...options
    };
    
    this.keyCache = new Map();
    this.encryptionSupported = this.detectCryptoSupport();
    this.storageBackend = this.selectStorageBackend();
    
    if (this.encryptionSupported) {
      this.initCryptoKeys();
    }
  }
  
  // 检测加密支持
  detectCryptoSupport() {
    return typeof window.crypto !== 'undefined' && 
           typeof window.crypto.subtle !== 'undefined';
  }
  
  // 选择存储后端
  selectStorageBackend() {
    if (this.options.storageBackend !== 'auto') {
      return this.options.storageBackend;
    }
    
    // 自动选择最佳存储后端
    try {
      if (typeof window.indexedDB !== 'undefined') {
        return 'indexedDB';
      } else if (typeof window.localStorage !== 'undefined') {
        // 测试 localStorage 是否可用
        window.localStorage.setItem('test', 'test');
        window.localStorage.removeItem('test');
        return 'localStorage';
      } else if (typeof window.sessionStorage !== 'undefined') {
        return 'sessionStorage';
      }
    } catch (error) {
      console.warn('Storage detection failed:', error);
    }
    
    return 'memory';
  }
  
  // 初始化加密密钥
  async initCryptoKeys() {
    try {
      // 从安全来源获取或生成密钥
      this.masterKey = await this.deriveKeyFromPassword(
        this.options.encryptionPassword || 'default-password',
        'master-key'
      );
      
      console.log('Crypto keys initialized');
    } catch (error) {
      console.error('Failed to initialize crypto keys:', error);
      this.encryptionSupported = false;
    }
  }
  
  // 从密码派生密钥
  async deriveKeyFromPassword(password, salt) {
    const encoder = new TextEncoder();
    const passwordBuffer = encoder.encode(password);
    const saltBuffer = encoder.encode(salt);
    
    // 导入密码作为密钥材料
    const keyMaterial = await crypto.subtle.importKey(
      'raw',
      passwordBuffer,
      'PBKDF2',
      false,
      ['deriveKey']
    );
    
    // 派生密钥
    const key = await crypto.subtle.deriveKey(
      {
        name: 'PBKDF2',
        salt: saltBuffer,
        iterations: this.options.keyDerivationIterations,
        hash: 'SHA-256'
      },
      keyMaterial,
      { name: 'AES-GCM', length: 256 },
      false,
      ['encrypt', 'decrypt']
    );
    
    return key;
  }
  
  // 生成数据特定密钥
  async getDataKey(keyName) {
    if (this.keyCache.has(keyName)) {
      return this.keyCache.get(keyName);
    }
    
    const key = await this.deriveKeyFromPassword(
      this.options.encryptionPassword || 'default-password',
      `data-key-${keyName}`
    );
    
    this.keyCache.set(keyName, key);
    return key;
  }
  
  // 加密数据
  async encryptData(data, keyName = 'default') {
    if (!this.encryptionSupported) {
      return data;
    }
    
    try {
      const key = await this.getDataKey(keyName);
      const encoder = new TextEncoder();
      const dataBuffer = encoder.encode(JSON.stringify(data));
      
      // 生成随机初始化向量
      const iv = crypto.getRandomValues(new Uint8Array(12));
      
      // 加密数据
      const encryptedBuffer = await crypto.subtle.encrypt(
        {
          name: 'AES-GCM',
          iv: iv
        },
        key,
        dataBuffer
      );
      
      // 组合 IV 和加密数据
      const combinedBuffer = new Uint8Array(iv.length + encryptedBuffer.byteLength);
      combinedBuffer.set(iv, 0);
      combinedBuffer.set(new Uint8Array(encryptedBuffer), iv.length);
      
      // 转换为 base64
      const base64String = btoa(String.fromCharCode.apply(null, combinedBuffer));
      
      return {
        encrypted: true,
        algorithm: this.options.encryptionAlgorithm,
        data: base64String,
        keyName
      };
    } catch (error) {
      console.error('Encryption failed:', error);
      return data;
    }
  }
  
  // 解密数据
  async decryptData(encryptedData, keyName = 'default') {
    if (!encryptedData.encrypted || !this.encryptionSupported) {
      return encryptedData;
    }
    
    try {
      const key = await this.getDataKey(keyName);
      
      // 从 base64 解码
      const combinedBuffer = Uint8Array.from(atob(encryptedData.data), c => c.charCodeAt(0));
      
      // 提取 IV 和加密数据
      const iv = combinedBuffer.slice(0, 12);
      const encryptedBuffer = combinedBuffer.slice(12);
      
      // 解密数据
      const decryptedBuffer = await crypto.subtle.decrypt(
        {
          name: 'AES-GCM',
          iv: iv
        },
        key,
        encryptedBuffer
      );
      
      const decoder = new TextDecoder();
      const decryptedString = decoder.decode(decryptedBuffer);
      
      return JSON.parse(decryptedString);
    } catch (error) {
      console.error('Decryption failed:', error);
      return encryptedData;
    }
  }
  
  // 安全存储数据
  async set(key, value, options = {}) {
    const {
      encrypt = true,
      ttl = null,
      keyName = 'default',
      ...storageOptions
    } = options;
    
    let processedValue = value;
    
    // 加密数据
    if (encrypt && this.encryptionSupported) {
      processedValue = await this.encryptData(value, keyName);
    }
    
    // 添加元数据
    const storageItem = {
      value: processedValue,
      meta: {
        encrypted: encrypt,
        keyName,
        createdAt: Date.now(),
        expiresAt: ttl ? Date.now() + ttl : null,
        version: '1.0'
      }
    };
    
    // 存储到后端
    return this.storeToBackend(key, storageItem, storageOptions);
  }
  
  // 从后端存储数据
  async storeToBackend(key, value, options) {
    switch (this.storageBackend) {
      case 'indexedDB':
        return this.storeToIndexedDB(key, value, options);
      case 'localStorage':
      case 'sessionStorage':
        return this.storeToWebStorage(key, value, options);
      default:
        return this.storeToMemory(key, value, options);
    }
  }
  
  // 存储到 IndexedDB
  async storeToIndexedDB(key, value, options) {
    // 简化的 IndexedDB 存储
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('SecureStorageDB', 1);
      
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        if (!db.objectStoreNames.contains('secureData')) {
          db.createObjectStore('secureData', { keyPath: 'key' });
        }
      };
      
      request.onsuccess = (event) => {
        const db = event.target.result;
        const transaction = db.transaction(['secureData'], 'readwrite');
        const store = transaction.objectStore('secureData');
        
        const item = { key, ...value };
        const putRequest = store.put(item);
        
        putRequest.onsuccess = () => resolve(true);
        putRequest.onerror = (error) => reject(error);
      };
      
      request.onerror = (error) => reject(error);
    });
  }
  
  // 存储到 Web Storage
  storeToWebStorage(key, value, options) {
    const storage = this.storageBackend === 'localStorage' ? 
      window.localStorage : window.sessionStorage;
    
    try {
      storage.setItem(key, JSON.stringify(value));
      return true;
    } catch (error) {
      console.error('Web storage failed:', error);
      return false;
    }
  }
  
  // 存储到内存
  storeToMemory(key, value, options) {
    this.memoryStorage = this.memoryStorage || new Map();
    this.memoryStorage.set(key, value);
    return true;
  }
  
  // 安全获取数据
  async get(key, defaultValue = null) {
    // 从后端获取数据
    const storageItem = await this.getFromBackend(key);
    
    if (!storageItem) {
      return defaultValue;
    }
    
    // 检查是否过期
    if (storageItem.meta.expiresAt && Date.now() > storageItem.meta.expiresAt) {
      await this.remove(key);
      return defaultValue;
    }
    
    let value = storageItem.value;
    
    // 解密数据
    if (storageItem.meta.encrypted) {
      value = await this.decryptData(value, storageItem.meta.keyName);
    }
    
    return value;
  }
  
  // 从后端获取数据
  async getFromBackend(key) {
    switch (this.storageBackend) {
      case 'indexedDB':
        return this.getFromIndexedDB(key);
      case 'localStorage':
      case 'sessionStorage':
        return this.getFromWebStorage(key);
      default:
        return this.getFromMemory(key);
    }
  }
  
  // 从 IndexedDB 获取
  async getFromIndexedDB(key) {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('SecureStorageDB', 1);
      
      request.onsuccess = (event) => {
        const db = event.target.result;
        const transaction = db.transaction(['secureData'], 'readonly');
        const store = transaction.objectStore('secureData');
        const getRequest = store.get(key);
        
        getRequest.onsuccess = (event) => {
          resolve(event.target.result);
        };
        
        getRequest.onerror = (error) => reject(error);
      };
      
      request.onerror = (error) => reject(error);
    });
  }
  
  // 从 Web Storage 获取
  getFromWebStorage(key) {
    const storage = this.storageBackend === 'localStorage' ? 
      window.localStorage : window.sessionStorage;
    
    try {
      const item = storage.getItem(key);
      return item ? JSON.parse(item) : null;
    } catch (error) {
      console.error('Web storage read failed:', error);
      return null;
    }
  }
  
  // 从内存获取
  getFromMemory(key) {
    return this.memoryStorage ? this.memoryStorage.get(key) || null : null;
  }
  
  // 删除数据
  async remove(key) {
    switch (this.storageBackend) {
      case 'indexedDB':
        return this.removeFromIndexedDB(key);
      case 'localStorage':
      case 'sessionStorage':
        return this.removeFromWebStorage(key);
      default:
        return this.removeFromMemory(key);
    }
  }
  
  // 从 IndexedDB 删除
  async removeFromIndexedDB(key) {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('SecureStorageDB', 1);
      
      request.onsuccess = (event) => {
        const db = event.target.result;
        const transaction = db.transaction(['secureData'], 'readwrite');
        const store = transaction.objectStore('secureData');
        const deleteRequest = store.delete(key);
        
        deleteRequest.onsuccess = () => resolve(true);
        deleteRequest.onerror = (error) => reject(error);
      };
      
      request.onerror = (error) => reject(error);
    });
  }
  
  // 从 Web Storage 删除
  removeFromWebStorage(key) {
    const storage = this.storageBackend === 'localStorage' ? 
      window.localStorage : window.sessionStorage;
    
    try {
      storage.removeItem(key);
      return true;
    } catch (error) {
      console.error('Web storage delete failed:', error);
      return false;
    }
  }
  
  // 从内存删除
  removeFromMemory(key) {
    if (this.memoryStorage) {
      return this.memoryStorage.delete(key);
    }
    return true;
  }
  
  // 清空所有数据
  async clear() {
    switch (this.storageBackend) {
      case 'indexedDB':
        return this.clearIndexedDB();
      case 'localStorage':
      case 'sessionStorage':
        return this.clearWebStorage();
      default:
        return this.clearMemory();
    }
  }
  
  // 清空 IndexedDB
  async clearIndexedDB() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('SecureStorageDB', 1);
      
      request.onsuccess = (event) => {
        const db = event.target.result;
        const transaction = db.transaction(['secureData'], 'readwrite');
        const store = transaction.objectStore('secureData');
        const clearRequest = store.clear();
        
        clearRequest.onsuccess = () => resolve(true);
        clearRequest.onerror = (error) => reject(error);
      };
      
      request.onerror = (error) => reject(error);
    });
  }
  
  // 清空 Web Storage
  clearWebStorage() {
    const storage = this.storageBackend === 'localStorage' ? 
      window.localStorage : window.sessionStorage;
    
    try {
      storage.clear();
      return true;
    } catch (error) {
      console.error('Web storage clear failed:', error);
      return false;
    }
  }
  
  // 清空内存
  clearMemory() {
    if (this.memoryStorage) {
      this.memoryStorage.clear();
    }
    return true;
  }
  
  // 获取存储统计信息
  async getStats() {
    const stats = {
      backend: this.storageBackend,
      encryptionSupported: this.encryptionSupported,
      items: 0,
      size: 0
    };
    
    // 根据后端获取统计信息
    switch (this.storageBackend) {
      case 'indexedDB':
        const dbItems = await this.getIndexedDBStats();
        stats.items = dbItems.count;
        stats.size = dbItems.size;
        break;
      case 'localStorage':
      case 'sessionStorage':
        const wsStats = this.getWebStorageStats();
        stats.items = wsStats.items;
        stats.size = wsStats.size;
        break;
      default:
        stats.items = this.memoryStorage ? this.memoryStorage.size : 0;
        stats.size = 0; // 内存大小难以准确计算
    }
    
    return stats;
  }
  
  // 获取 IndexedDB 统计信息
  async getIndexedDBStats() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('SecureStorageDB', 1);
      
      request.onsuccess = async (event) => {
        const db = event.target.result;
        const transaction = db.transaction(['secureData'], 'readonly');
        const store = transaction.objectStore('secureData');
        const countRequest = store.count();
        
        countRequest.onsuccess = (event) => {
          resolve({
            count: event.target.result,
            size: 0 // 实际项目中可以遍历计算大小
          });
        };
        
        countRequest.onerror = (error) => reject(error);
      };
      
      request.onerror = (error) => reject(error);
    });
  }
  
  // 获取 Web Storage 统计信息
  getWebStorageStats() {
    const storage = this.storageBackend === 'localStorage' ? 
      window.localStorage : window.sessionStorage;
    
    let items = 0;
    let size = 0;
    
    for (let i = 0; i < storage.length; i++) {
      const key = storage.key(i);
      const value = storage.getItem(key);
      items++;
      size += (key.length + value.length) * 2; // UTF-16 估算
    }
    
    return { items, size };
  }
}

// 使用示例
class SecureStorageExample {
  static async demonstrate() {
    // 创建安全存储实例
    const secureStorage = new SecureStorage({
      encryptionPassword: 'strong-password-123',
      storageBackend: 'auto'
    });
    
    // 存储敏感数据
    await secureStorage.set('credit_card', {
      number: '4111111111111111',
      expiry: '12/25',
      cvv: '123'
    }, {
      encrypt: true,
      ttl: 3600000, // 1小时过期
      keyName: 'financial'
    });
    
    // 存储非敏感数据
    await secureStorage.set('user_preferences', {
      theme: 'dark',
      language: 'en-US',
      notifications: true
    }, { encrypt: false });
    
    // 获取数据
    const cardData = await secureStorage.get('credit_card');
    const preferences = await secureStorage.get('user_preferences');
    
    console.log('Credit card data:', cardData);
    console.log('User preferences:', preferences);
    
    // 获取统计信息
    const stats = await secureStorage.getStats();
    console.log('Storage stats:', stats);
    
    return secureStorage;
  }
}

五、存储性能监控和调优

5.1 存储性能监控器
javascript 复制代码
class StoragePerformanceMonitor {
  constructor() {
    this.metrics = {
      operations: {
        read: { count: 0, totalTime: 0, failures: 0 },
        write: { count: 0, totalTime: 0, failures: 0 },
        delete: { count: 0, totalTime: 0, failures: 0 }
      },
      sizes: {
        localStorage: 0,
        sessionStorage: 0,
        cookies: 0,
        indexedDB: 0
      },
      limits: {
        localStorage: 5 * 1024 * 1024, // 5MB
        sessionStorage: 5 * 1024 * 1024, // 5MB
        cookies: 4096, // 4KB
        indexedDB: 0 // 无明确限制
      }
    };
    
    this.sampleInterval = null;
    this.history = [];
    this.maxHistorySize = 1000;
    
    this.startMonitoring();
  }
  
  // 开始监控
  startMonitoring(interval = 5000) {
    this.sampleInterval = setInterval(() => {
      this.captureSnapshot();
    }, interval);
    
    // 初始快照
    this.captureSnapshot();
    
    // 监听存储事件
    window.addEventListener('storage', this.handleStorageEvent.bind(this));
    
    // 监听 beforeunload 以保存最终状态
    window.addEventListener('beforeunload', () => {
      this.saveMetricsToLocalStorage();
    });
  }
  
  // 停止监控
  stopMonitoring() {
    if (this.sampleInterval) {
      clearInterval(this.sampleInterval);
      this.sampleInterval = null;
    }
    
    window.removeEventListener('storage', this.handleStorageEvent);
    window.removeEventListener('beforeunload', this.saveMetricsToLocalStorage);
  }
  
  // 处理存储事件
  handleStorageEvent(event) {
    const metricType = event.newValue ? 'write' : 'delete';
    this.recordOperation(metricType, event.key, 0, false);
  }
  
  // 记录操作
  recordOperation(type, key, duration, success = true) {
    const operation = this.metrics.operations[type];
    
    if (operation) {
      operation.count++;
      operation.totalTime += duration;
      
      if (!success) {
        operation.failures++;
      }
    }
    
    // 添加到历史记录
    this.addToHistory({
      timestamp: Date.now(),
      type,
      key,
      duration,
      success
    });
  }
  
  // 添加到历史记录
  addToHistory(entry) {
    this.history.push(entry);
    
    // 限制历史记录大小
    if (this.history.length > this.maxHistorySize) {
      this.history = this.history.slice(-this.maxHistorySize);
    }
  }
  
  // 捕获快照
  captureSnapshot() {
    const snapshot = {
      timestamp: Date.now(),
      metrics: { ...this.metrics },
      sizes: this.calculateSizes(),
      performance: this.calculatePerformance()
    };
    
    // 更新当前大小
    this.metrics.sizes = snapshot.sizes;
    
    // 保存到历史
    this.history.push(snapshot);
    
    // 限制历史记录大小
    if (this.history.length > this.maxHistorySize) {
      this.history = this.history.slice(-this.maxHistorySize);
    }
    
    return snapshot;
  }
  
  // 计算存储大小
  calculateSizes() {
    const sizes = {
      localStorage: 0,
      sessionStorage: 0,
      cookies: 0,
      indexedDB: 0
    };
    
    // 计算 localStorage 大小
    try {
      let localStorageSize = 0;
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        const value = localStorage.getItem(key);
        localStorageSize += (key.length + value.length) * 2;
      }
      sizes.localStorage = localStorageSize;
    } catch (error) {
      console.warn('Failed to calculate localStorage size:', error);
    }
    
    // 计算 sessionStorage 大小
    try {
      let sessionStorageSize = 0;
      for (let i = 0; i < sessionStorage.length; i++) {
        const key = sessionStorage.key(i);
        const value = sessionStorage.getItem(key);
        sessionStorageSize += (key.length + value.length) * 2;
      }
      sizes.sessionStorage = sessionStorageSize;
    } catch (error) {
      console.warn('Failed to calculate sessionStorage size:', error);
    }
    
    // 计算 cookies 大小
    try {
      sizes.cookies = document.cookie.length * 2; // 简单估算
    } catch (error) {
      console.warn('Failed to calculate cookies size:', error);
    }
    
    return sizes;
  }
  
  // 计算性能指标
  calculatePerformance() {
    const perf = {
      averageReadTime: 0,
      averageWriteTime: 0,
      readSuccessRate: 1,
      writeSuccessRate: 1,
      storageUsage: {}
    };
    
    const readOps = this.metrics.operations.read;
    const writeOps = this.metrics.operations.write;
    
    if (readOps.count > 0) {
      perf.averageReadTime = readOps.totalTime / readOps.count;
      perf.readSuccessRate = (readOps.count - readOps.failures) / readOps.count;
    }
    
    if (writeOps.count > 0) {
      perf.averageWriteTime = writeOps.totalTime / writeOps.count;
      perf.writeSuccessRate = (writeOps.count - writeOps.failures) / writeOps.count;
    }
    
    // 计算存储使用率
    Object.keys(this.metrics.sizes).forEach(storageType => {
      const size = this.metrics.sizes[storageType];
      const limit = this.metrics.limits[storageType];
      
      if (limit > 0) {
        perf.storageUsage[storageType] = {
          size,
          limit,
          percentage: (size / limit) * 100,
          remaining: limit - size
        };
      } else {
        perf.storageUsage[storageType] = {
          size,
          limit: 'unlimited',
          percentage: 0,
          remaining: Infinity
        };
      }
    });
    
    return perf;
  }
  
  // 获取性能报告
  getReport() {
    const snapshot = this.captureSnapshot();
    
    return {
      summary: {
        totalOperations: Object.values(this.metrics.operations).reduce(
          (sum, op) => sum + op.count, 0
        ),
        totalFailures: Object.values(this.metrics.operations).reduce(
          (sum, op) => sum + op.failures, 0
        ),
        overallSuccessRate: 1 - (
          Object.values(this.metrics.operations).reduce(
            (sum, op) => sum + op.failures, 0
          ) / Math.max(1, Object.values(this.metrics.operations).reduce(
            (sum, op) => sum + op.count, 0
          ))
        ),
        monitoringDuration: this.history.length > 0 ? 
          Date.now() - this.history[0].timestamp : 0
      },
      current: snapshot,
      trends: this.calculateTrends(),
      recommendations: this.generateRecommendations()
    };
  }
  
  // 计算趋势
  calculateTrends() {
    if (this.history.length < 2) return {};
    
    const recent = this.history.slice(-10); // 最近10个样本
    const trends = {};
    
    // 计算操作趋势
    ['read', 'write', 'delete'].forEach(opType => {
      const counts = recent.map(s => s.metrics.operations[opType].count);
      const avgCount = counts.reduce((a, b) => a + b, 0) / counts.length;
      
      trends[opType] = {
        averagePerSample: avgCount,
        trend: counts.length > 1 ? 
          (counts[counts.length - 1] - counts[0]) / counts[0] : 0
      };
    });
    
    // 计算大小趋势
    Object.keys(this.metrics.sizes).forEach(storageType => {
      const sizes = recent.map(s => s.sizes[storageType]);
      trends[storageType] = {
        averageSize: sizes.reduce((a, b) => a + b, 0) / sizes.length,
        growthRate: sizes.length > 1 ? 
          (sizes[sizes.length - 1] - sizes[0]) / sizes[0] : 0
      };
    });
    
    return trends;
  }
  
  // 生成优化建议
  generateRecommendations() {
    const recommendations = [];
    const perf = this.calculatePerformance();
    
    // 检查存储使用率
    Object.entries(perf.storageUsage).forEach(([storageType, usage]) => {
      if (usage.percentage > 80) {
        recommendations.push({
          type: 'warning',
          message: `${storageType} usage is at ${usage.percentage.toFixed(1)}%`,
          suggestion: 'Consider cleaning up unused data or migrating to IndexedDB',
          priority: 'high'
        });
      } else if (usage.percentage > 50) {
        recommendations.push({
          type: 'info',
          message: `${storageType} usage is at ${usage.percentage.toFixed(1)}%`,
          suggestion: 'Monitor storage usage and consider optimization',
          priority: 'medium'
        });
      }
    });
    
    // 检查操作失败率
    if (perf.readSuccessRate < 0.95) {
      recommendations.push({
        type: 'error',
        message: `Read operation success rate is low: ${(perf.readSuccessRate * 100).toFixed(1)}%`,
        suggestion: 'Check storage availability and error handling',
        priority: 'high'
      });
    }
    
    if (perf.writeSuccessRate < 0.95) {
      recommendations.push({
        type: 'error',
        message: `Write operation success rate is low: ${(perf.writeSuccessRate * 100).toFixed(1)}%`,
        suggestion: 'Storage may be full or corrupted. Consider cleanup.',
        priority: 'high'
      });
    }
    
    // 检查性能
    if (perf.averageReadTime > 100) { // 超过100ms
      recommendations.push({
        type: 'warning',
        message: `Average read time is high: ${perf.averageReadTime.toFixed(1)}ms`,
        suggestion: 'Consider using IndexedDB for large datasets',
        priority: 'medium'
      });
    }
    
    if (perf.averageWriteTime > 100) { // 超过100ms
      recommendations.push({
        type: 'warning',
        message: `Average write time is high: ${perf.averageWriteTime.toFixed(1)}ms`,
        suggestion: 'Batch write operations or use web workers',
        priority: 'medium'
      });
    }
    
    return recommendations;
  }
  
  // 保存指标到本地存储
  saveMetricsToLocalStorage() {
    try {
      const report = this.getReport();
      localStorage.setItem('storage_performance_metrics', JSON.stringify(report));
      localStorage.setItem('storage_performance_history', JSON.stringify(this.history));
    } catch (error) {
      console.warn('Failed to save metrics:', error);
    }
  }
  
  // 从本地存储加载指标
  loadMetricsFromLocalStorage() {
    try {
      const savedReport = localStorage.getItem('storage_performance_metrics');
      const savedHistory = localStorage.getItem('storage_performance_history');
      
      if (savedReport) {
        const report = JSON.parse(savedReport);
        // 合并指标
        Object.assign(this.metrics, report.current.metrics);
      }
      
      if (savedHistory) {
        this.history = JSON.parse(savedHistory);
      }
    } catch (error) {
      console.warn('Failed to load metrics:', error);
    }
  }
  
  // 重置指标
  resetMetrics() {
    this.metrics = {
      operations: {
        read: { count: 0, totalTime: 0, failures: 0 },
        write: { count: 0, totalTime: 0, failures: 0 },
        delete: { count: 0, totalTime: 0, failures: 0 }
      },
      sizes: {
        localStorage: 0,
        sessionStorage: 0,
        cookies: 0,
        indexedDB: 0
      },
      limits: {
        localStorage: 5 * 1024 * 1024,
        sessionStorage: 5 * 1024 * 1024,
        cookies: 4096,
        indexedDB: 0
      }
    };
    
    this.history = [];
  }
  
  // 导出数据
  exportData(format = 'json') {
    const report = this.getReport();
    
    switch (format) {
      case 'json':
        return JSON.stringify(report, null, 2);
      case 'csv':
        return this.convertToCSV(report);
      default:
        return report;
    }
  }
  
  // 转换为CSV
  convertToCSV(report) {
    const rows = [];
    
    // 添加摘要行
    rows.push('Section,Key,Value');
    rows.push(`Summary,Total Operations,${report.summary.totalOperations}`);
    rows.push(`Summary,Total Failures,${report.summary.totalFailures}`);
    rows.push(`Summary,Success Rate,${report.summary.overallSuccessRate}`);
    
    // 添加性能行
    rows.push('Performance,Average Read Time,${report.current.performance.averageReadTime}');
    rows.push('Performance,Average Write Time,${report.current.performance.averageWriteTime}');
    
    // 添加存储使用行
    Object.entries(report.current.performance.storageUsage).forEach(([storage, usage]) => {
      rows.push(`Storage Usage,${storage},${usage.percentage.toFixed(1)}%`);
    });
    
    return rows.join('\n');
  }
}

// 使用示例
class StorageMonitorExample {
  static demonstrate() {
    // 创建性能监控器
    const monitor = new StoragePerformanceMonitor();
    
    // 模拟一些存储操作
    setTimeout(() => {
      // 记录读取操作
      const readStart = performance.now();
      localStorage.getItem('test_key');
      const readDuration = performance.now() - readStart;
      monitor.recordOperation('read', 'test_key', readDuration, true);
      
      // 记录写入操作
      const writeStart = performance.now();
      localStorage.setItem('test_key', 'test_value');
      const writeDuration = performance.now() - writeStart;
      monitor.recordOperation('write', 'test_key', writeDuration, true);
    }, 1000);
    
    // 获取报告
    setTimeout(() => {
      const report = monitor.getReport();
      console.log('Storage Performance Report:', report);
      
      // 导出数据
      const jsonExport = monitor.exportData('json');
      console.log('JSON Export:', jsonExport);
      
      // 停止监控
      monitor.stopMonitoring();
    }, 5000);
    
    return monitor;
  }
}

总结

本文全面探讨了浏览器存储相关的API和技术,包括:

  1. 本地存储封装: 增强的localStorage/sessionStorage封装,支持加密、压缩、过期时间等高级功能
  2. IndexedDB高级封装: 完整的数据库操作包装器,支持迁移、事务、查询构建等
  3. Cookie操作库: 完整的Cookie管理器,支持跨域操作和安全性增强
  4. 安全存储实践: 数据加密、密钥管理、安全最佳实践
  5. 存储性能监控: 实时监控存储使用情况和性能指标
  6. 智能存储选择器: 根据场景自动选择最佳存储方案

关键要点

  1. 安全性优先: 始终对敏感数据进行加密,避免在客户端存储敏感信息
  2. 容量管理: 监控存储使用情况,及时清理过期数据
  3. 性能优化: 批量操作、延迟写入、合理选择存储后端
  4. 兼容性考虑: 提供降级方案,确保在不支持某些API的浏览器中正常运作
  5. 用户体验: 异步操作避免阻塞UI,提供适当的加载状态
  6. 数据完整性: 实现数据验证、版本控制和迁移策略

最佳实践建议

  1. 分层存储策略:
  • 频繁访问的小数据:使用内存缓存
  • 用户会话数据:使用sessionStorage
  • 长期偏好设置:使用localStorage
  • 大量结构化数据:使用IndexedDB
  • 身份验证令牌:使用HttpOnly Cookie
  1. 数据生命周期管理:
  • 为所有存储数据设置合理的过期时间
  • 实现自动清理机制
  • 提供数据导出/导入功能
  1. 错误处理和降级:
  • 捕获所有存储操作异常
  • 提供友好的错误提示
  • 实现降级到更简单的存储方案
  1. 隐私合规:
  • 遵循GDPR、CCPA等隐私法规
  • 提供用户数据清除功能
  • 明确告知用户数据使用方式

通过合理使用这些技术和策略,开发者可以构建出既安全又高效的Web应用存储系统,提供优秀的用户体验。

相关推荐
HIT_Weston2 小时前
63、【Ubuntu】【Gitlab】拉出内网 Web 服务:Gitlab 配置审视(七)
前端·ubuntu·gitlab
jinxinyuuuus2 小时前
vsGPU:硬件参数的数据仓库设计、ETL流程与前端OLAP分析
前端·数据仓库·etl
Evan芙2 小时前
Nginx 平滑升级
数据库·nginx·ubuntu
小信丶3 小时前
解决 pnpm dev 报错:系统禁止运行脚本的问题
前端·vue.js·windows·npm
૮・ﻌ・3 小时前
Vue3:组合式API、Vue3.3新特性、Pinia
前端·javascript·vue3
前端不太难3 小时前
RN + TypeScript 项目越写越乱?如何规范架构?
前端·javascript·typescript
神算大模型APi--天枢6463 小时前
全栈自主可控:国产算力平台重塑大模型后端开发与部署生态
大数据·前端·人工智能·架构·硬件架构
苏打水com3 小时前
第十五篇:Day43-45 前端性能优化进阶——从“可用”到“极致”(对标职场“高并发场景优化”需求)
前端·css·vue·html·js
亚林瓜子3 小时前
mysql命令行手动导入csv数据到指定表
数据库·mysql·gui·csv·cli·db·import