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

参考

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

相关推荐
Best_卡卡4 分钟前
前端性能-HTTP缓存
前端·http·缓存
GIS好难学1 小时前
《Openlayers零基础教程》第六课:地图控件
前端·javascript·零基础·openlayers
桃园码工2 小时前
3_CSS3 渐变 --[CSS3 进阶之路]
前端·css·css3·css3 渐变
NoneCoder3 小时前
JavaScript系列(22)--模块化进阶
开发语言·javascript·ecmascript
成长中的向日葵3 小时前
element-ui dialog弹窗 设置点击空白处不关闭
前端·vue.js
ihengshuai3 小时前
Gitlab流水线配置
前端·docker·gitlab·devops
alphaTabc3 小时前
从0到1实现一个插件系统
前端·javascript
前端太佬3 小时前
笔记-Big.js的使用
前端·javascript
Blushyes4 小时前
【 如快 Tauri 2 实践 】结合 pinia 实现本地文件存储响应式
前端·javascript·typescript
梦想CAD控件4 小时前
(WEB CAD SDK)网页CAD绘制条形码、二维码的教程
前端·javascript·vue.js