opendb 是一个返回 promise 的 indexeddb 初始化工具函数,接收数据库名、版本号和升级回调,自动处理版本升级、错误捕获与连接复用。

在 HTML5 中使用 IndexedDB 时,原生 API 是事件驱动、回调嵌套的,写起来繁琐且难以维护。封装一个 Promise 风格的数据库初始化工具函数,能显著提升可读性与复用性。
核心目标:返回 Promise 的 openDB 工具函数
该函数应接收数据库名、版本号和可选的升级逻辑,返回一个解析为 IDBDatabase 实例的 Promise。失败时 reject 错误,成功时 resolve 数据库对象,并确保只在必要时执行 upgrade 逻辑。
- 自动处理版本变更(仅当请求版本 > 当前版本时触发
onupgradeneeded) - 统一错误捕获(
onerror和onblocked可选处理) - 避免重复打开(内部缓存已打开的连接,相同 name + version 复用)
基础实现(兼容现代浏览器)
以下是一个轻量、无依赖的封装示例:
function openDB(name, version = 1, upgradeCb = null) {
return new Promise((resolve, reject) => {
const request = indexedDB.open(name, version);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (typeof upgradeCb === 'function') {
upgradeCb(db, event.oldVersion, event.newVersion, event.transaction);
}
};
// 可选:处理数据库被其他标签页占用的情况
request.onblocked = () => reject(new Error('Database is blocked — close other tabs using it'));
});
}
调用方式简洁直观:
openDB('myApp', 2, (db, old, _new, tx) => {
if (old console.log('Ready:', db))
.catch(err => console.error('Init failed:', err));
增强版:支持连接复用与自动关闭管理
实际项目中,频繁调用 openDB 可能导致冗余连接。可扩展为单例模式,按 name + version 缓存活跃连接,并提供显式关闭接口:
- 用
Map存储{[name]: Map<version promise>>}</version> - 每次调用先查缓存,命中则直接返回已 resolve 的 Promise
- 暴露
closeDB(name, version)主动释放连接(调用db.close()) - 监听
pagehide或beforeunload自动清理(谨慎使用,避免中断事务)
注意事项与避坑提示
Promise 封装虽好,但 IndexedDB 的底层约束不可忽视:
-
upgrade 回调中才能建库/表/索引:不在
onupgradeneeded里操作会报 InvalidStateError -
事务生命周期绑定于事件循环:不要在 Promise
.then()里直接开事务,应在 success 后立即用db.transaction() - 版本号必须是整数:传小数(如 1.1)会被截断为 1,导致升级不触发
-
同一时刻一个数据库只能有一个打开请求:并发调用
openDB不会冲突,但需确保 upgradeCb 是幂等或有版本判断逻辑
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










