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

参考

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

相关推荐
cwtlw19 分钟前
CSS学习记录11
前端·css·笔记·学习·其他
weisian15125 分钟前
中间件--MongoDB部署及初始化js脚本(docker部署,docker-entrypoint-initdb.d,数据迁移,自动化部署)
javascript·mongodb·中间件
轻动琴弦36 分钟前
nestjs+webpack打包成一个mainjs
前端·webpack·node.js
m0_7482361144 分钟前
前端怎么预览pdf
前端·pdf
快乐牛牛不要困难44 分钟前
前端将base64转pdf页面预览
前端
m0_748233641 小时前
Python Flask Web框架快速入门
前端·python·flask
凉辰1 小时前
使用FabricJS对大图像应用滤镜(巨坑)
前端
梓沂1 小时前
pom.xml中dependencyManagement的作用
xml·java·前端
m0_748250031 小时前
前端pdf预览方案
前端·pdf·状态模式
neeef_se1 小时前
【Linux】WG-Easy:基于 Docker 和 Web 面板的异地组网
linux·前端·docker