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,提升查询效率。
  • 索引优化:为查询频繁的字段创建索引。

参考

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

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端