前端使用 IndexedDB 存储

222 阅读3分钟

本文,我们来探讨前端浏览器中的存储 - IndexedDB

浏览器的缓存

浏览器的 Application 下面有如图存储方式 👇

浏览器存储方式

以上是谷歌浏览器的截图,其版本是 134.0.6998.89(正式版本) (x86_64)

老生常谈的存储 CookiesLocalStorageSessionStorage 有如下特点:

名称特点限制用途
Cookies跟随 HTTP 请求自动发送到服务器。可以设定过期时间存储空间小(通常为 4KB)适用于客户端和服务端之间传递小数据,比如会话标志
LocalStorage关闭浏览器也不会丢失数据存储空间有限(通常为5MB),只能存储字符串类型的数据适用于需要持久化存储的数据,如用户偏好
SessionStorage数据在浏览器会话期存储存储空间有限(通常为5MB),只能存储字符串类型的数据适合临时存储数据,比如表单数据

之前浏览器有两个数据库存储 WebSQLIndexedDB,但是 WebSQL 未能成为正式的 Web 标准,并逐渐被 IndexedDB 替代。

WebSQL

IndexedDB

认识 IndexedDB

IndexedDB 在现代主流的浏览器上的表现很好,基本没啥兼容性问题。如果是在业务型特定浏览器 webkit 内核上,更不用关心兼容性的问题。

当需要在浏览器中存储大量结构化数据,IndexedDB 提供了一个事务性的键值存储系统,允许我们在客户端存储和检索数据。它适用于需要离线存储和处理复杂数据的 WEB 应用。

IndexedDB 主要有以下的特点:

  • 异步操作IndexedDB 的所有操作都是一步的,这意味着它不会阻塞主线程,从而提高应用的响应速度。
  • 事务支持IndexedDB 支持事务操作,确保数据的一致性和完整性。事务可以是只读或者读写的。
  • 键值存储IndexedDB 中数据以键值对的形式存储,类似于 NoSQL 数据库。每个存储对象 Object Store 都有一个主键,用于唯一标识记录。
  • 索引IndexedDB 可以为对象存储创建索引,以便快速查询数据。索引可以是唯一的或非唯一的。
  • 版本控制IndexedDB 支持数据库版本控制,允许我们在升级数据库时进行结构性更改。
  • 存储限制IndexedDB 存储空间比较大。这取决不同浏览器的实现。在 Google Chrome 中,IndexedDB 默认存储配额通常为 60% 的可用磁盘空间。存储空间比 localStorage 大得多。

IndexedDB 使用

下面,我们将通过代码案例来讲解怎么去使用 IndexedDB

// 定义数据库
let db: IDBDatabase;
// 打开数据库
const request = indexedDB.open("requestDatabase");
// 创建表名
const storeName = "jimmyStore";

export interface IIndexedDBDataItem {
  id: string;
  value: string;
}

// 数据库打开错误
request.onerror = (event) => {
  console.error("无法打开数据库");
}

// 成功打开
request.onsucess = (event: Event) {
  db = (event.target as IDBOpenDBRequest).result;
  console.log("数据库打开成功", db);
}

// 数据库升级(第一次新建库也会触发,因为数据库从无到有算一次升级)
request.onupgradeneeded = async (event: IDBVersionChangeEvent) => {
  db = (event.target as IDBOpenDBRequest).result;
  if (!db.objectStoreNames.contains(storeName)) {
    // 创建数据库存储名称
    db.createObjectStore(storeName, { keyPath: "id" });
  }
}

// 添加数据
export const addIndexedDBData = (data: IIndexedDBDataItem): Promise<void> => {
  return new Promise((resolve, reject) => {
    // 创建事务
    const transaction = db.transaction([storeName], "readwrite");
    const objectStore = transaction.objectStore(storeName);
    const request = objectStore.add(data);
    request.onsucess = () => {
      resolve();
    }
    request.onerror = (event) => {
      reject(event);
    }
  })
}

// 删除存在的数据
export const deleteIndexedDBData = (id: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    const transaction = db.transaction([storeName], "readwrite");
    const objectStore = transaction.objectStore(storeName);
    const request = objectStore.delete(id); // 如果是删除全部的数据,我们可以使用 objectStore.clear() 来实现
    request.onsucess = () => {
      resolve();
    }
    request.onerror = () => {
      reject(event);
    }
  });
}

// 获取 indexedDB 数据
export const getIndexedDBData = (id: string): Promise<IIndexedDBDataItem | undefined> => {
  return new Promise((resolve, reject) => {
    const transaction = db.transaction([storeName], "readonly");
    const objectStore = transaction.objectStore(storeName);
    const request = objectStore.get(id);
    request.onsucess = () => {
      resolve();
    }
    request.onerror = () => {
      reject(event);
    }
  })
}

上面,我们实现了对数据库数据的写入,删除和获取。以谷歌为例,在 window 上,数据会被保存在 C:\Users\Jimmy(当前用户)\AppData\Local\Google\Chrome\User Data\Default\IndexedDB 下面 👇

IndexedDB Postion

参考