在前端开发中,随着功能的丰富和用户体验的优化,数据存储需求愈发复杂。然而,传统的 localStorage
和 cookie
面临 存储容量 的限制(通常仅 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);
});
}
}
使用提示
-
Promise 化操作:
- IndexedDB 原生 API 使用事件监听处理成功和失败,封装后利用
Promise
提升了可读性。
- IndexedDB 原生 API 使用事件监听处理成功和失败,封装后利用
-
自动化创建存储对象:
- 构造函数中检测是否存在指定的 Object Store,不存在时自动创建。
-
简化操作接口:
- 提供
set
和get
方法,便于直接读写数据。
- 提供
快速上手缓存大文件
-
可以通过上面的代码片段集成到项目中;
-
可以直接通过
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,提升查询效率。
- 索引优化:为查询频繁的字段创建索引。
参考
希望这篇文章对你有帮助,欢迎留言交流更多使用心得!