Storage / Cookie 存储空间不够?3 分钟搞定大文件缓存!

在前端开发中,随着功能的丰富和用户体验的优化,数据存储需求愈发复杂。然而,传统的 localStoragecookie 面临 存储容量 的限制(通常仅 5MB 左右),这对需要缓存大量数据的场景尤为不友好。

本文将带你快速上手 IndexedDB,展示如何利用 IndexedDB 技术高效缓存大文件。

什么是 IndexedDB?

IndexedDB 是一种运行在浏览器中的低级别 API,适合存储大量结构化数据。与 localStorage 不同,IndexedDB 的特点包括:

  • 存储容量大:支持数百 MB 甚至 GB 的数据。
  • 键值存储:数据以键值对形式存储。
  • 事务支持:操作更加安全。
  • 异步 API:不会阻塞主线程。

IndexedDB 封装示例

以下是一个典型的 IndexedDB 类封装实现,帮助你快速集成该功能。

ts 复制代码
export interface IndexedDBType {
  dbName: string;
  dbVersion: number;
  dbStoreName: string;
}

export const defaultIndexedDB: IndexedDBType = {
  dbName: 'your-db-name',
  dbVersion: 1,
  dbStoreName: 'your-db-store-name',
};

export class IndexedDB<T = any> {
  private readonly dbStoreName: string;
  private readonly dbPromise: Promise<IDBDatabase>;

  constructor(
    {
      dbName,
      dbVersion,
      dbStoreName,
    }: IndexedDBType = defaultIndexedDB,
  ) {
    this.dbStoreName = dbStoreName;

    this.dbPromise = new Promise((resolve, reject) => {
      const request = indexedDB.open(dbName, dbVersion);

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;
        if (!db.objectStoreNames.contains(dbStoreName)) {
          db.createObjectStore(dbStoreName, { keyPath: 'id' });
        }
      };

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async set(key: string, value: T): Promise<void> {
    const db = await this.dbPromise;
    const transaction = db.transaction(this.dbStoreName, 'readwrite');
    const store = transaction.objectStore(this.dbStoreName);
    store.put({ id: key, value });
  }

  async get(key: string): Promise<T | undefined> {
    const db = await this.dbPromise;
    const transaction = db.transaction(this.dbStoreName, 'readonly');
    const store = transaction.objectStore(this.dbStoreName);
    return new Promise((resolve, reject) => {
      const request = store.get(key);
      request.onsuccess = () => resolve(request.result?.value);
      request.onerror = () => reject(request.error);
    });
  }
}

使用提示

  1. Promise 化操作

    • IndexedDB 原生 API 使用事件监听处理成功和失败,封装后利用 Promise 提升了可读性。
  2. 自动化创建存储对象

    • 构造函数中检测是否存在指定的 Object Store,不存在时自动创建。
  3. 简化操作接口

    • 提供 setget 方法,便于直接读写数据。

快速上手缓存大文件

  • 可以通过上面的代码片段集成到项目中;

  • 可以直接通过 npm install @kieranwv/utils 或者 npm install dexie 使用。

以下是一个简单示例,展示利用 @kieranwv/utils 的 IndexedDB 封装来存储和读取数据:

ts 复制代码
import { IndexedDB } from '@kieranwv/utils';

// 初始化 IndexedDB
const db = new IndexedDB<{ id: string; value: any }>({
  dbName: 'MyAppDB',
  dbVersion: 1,
  dbStoreName: 'AppStore',
});

// 写入数据
async function saveData(key: string, data: any) {
  await db.set(key, data);
  console.log(`数据 ${key} 已成功存储`);
}

// 读取数据
async function loadData(key: string) {
  const result = await db.get(key);
  if (result) {
    console.log(`读取成功:`, result);
    return result;
  } else {
    console.log(`数据 ${key} 不存在`);
    return null;
  }
}

// 删除数据
async function deleteData(key: string) {
  await db.delete(key);
  console.log(`数据 ${key} 已删除`);
}

// 测试用例
(async () => {
  await saveData('user1', { name: 'Alice', age: 30 });
  const user = await loadData('user1');
  console.log(user); // 输出 { name: 'Alice', age: 30 }
  await deleteData('user1');
})();

通过该实现,你可以轻松地缓存音频、视频、图片等大文件,而无需担心存储空间不足的问题。

性能优化

  • 按需清理 :利用 delete 方法及时清理无用数据。
  • 分区存储:根据不同数据类型划分多个 Object Store,提升查询效率。
  • 索引优化:为查询频繁的字段创建索引。

参考

希望这篇文章对你有帮助,欢迎留言交流更多使用心得!

相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter9 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友9 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js