IndexedDB 原生 API 事件驱动、冗长易错,需用 Promise 封装(如 open、get 等)支持 async/await;封装核心是监听 IDBRequest 的 onsuccess/onerror;但须注意事务生命周期、版本升级限制及大对象有效性,推荐使用成熟的 idb 库。

IndexedDB 原生 API 是基于事件的,写起来冗长且容易出错。用 Promise 封装后,能用 async/await 写法让逻辑更清晰、错误处理更统一。
把 open、add、get 等操作包装成 Promise
核心思路是:对每个 IDBRequest 对象监听 onsuccess 和 onerror,手动 resolve 或 reject。
- open:封装数据库打开过程,返回数据库实例的 Promise
- add / put / delete / get / getAll:对 objectStore 操作封装,避免重复写 request.onupgradeneeded / onsuccess
- 注意:所有封装函数内部必须在事务活跃时执行(比如在
transaction.oncomplete之外调用get会报错)
常用封装示例(轻量级,不依赖库)
例如封装一个通用的 idbGet:
function idbGet(dbName, storeName, key) {
return new Promise((resolve, reject) => {
const req = indexedDB.open(dbName);
req.onerror = () => reject(req.error);
req.onsuccess = () => {
const db = req.result;
const tx = db.transaction(storeName, 'readonly');
const store = tx.objectStore(storeName);
const getReq = store.get(key);
getReq.onsuccess = () => resolve(getReq.result);
getReq.onerror = () => reject(getReq.error);
};
});
}
// 使用
async function fetchUser(id) {
try {
const user = await idbGet('mydb', 'users', id);
console.log(user);
} catch (err) {
console.error('读取失败:', err);
}
}
推荐用 idb 库(更可靠)
手动封装容易漏掉边界情况(如版本升级、连接中断、事务自动关闭)。社区成熟的 idb 库已做好这些:
立即学习“Java免费学习笔记(深入)”;
- 提供
openDB、transaction、put、get等 Promise 化 API - 自动管理连接和事务生命周期
- 支持 TypeScript,API 设计简洁
import { openDB } from 'idb';
const db = await openDB('mydb', 1, {
upgrade(db) {
db.createObjectStore('users', { keyPath: 'id' });
}
});
await db.put('users', { id: 1, name: 'Alice' });
const user = await db.get('users', 1);
关键注意事项
Promise 化不能绕过 IndexedDB 的底层限制:
- 事务有生命周期 —— 所有操作必须在
transaction.oncomplete触发前完成,否则报 “Failed to execute 'xxx' on 'IDBObjectStore': The transaction has finished.” - 版本升级只能在
onupgradeneeded中进行结构变更(如新建 store),不能在普通事务里改 - 大对象(如 Blob、File)可直接存,但需确保它们在事务期间有效(避免被 GC)


















