如何在IndexedDB创建多个对象存储并在全部创建完成后获得通知?
问题解答
你遇到的核心问题是对IndexedDB升级事务的机制理解有误:你创建的两个对象存储都属于同一个数据库升级事务,单个对象存储的transaction指向的就是这个全局升级事务——它的oncomplete不会在单个存储创建后触发,而是要等整个升级流程(所有存储创建、索引配置等操作)全部完成后才会执行,所以你单独绑定的两个回调不会被调用。
正确实现方式
实际上dbOpenRequest.onsuccess确实会在所有对象存储创建完成后才触发:只有当升级事务成功提交,数据库才会打开成功,进而触发onsuccess事件。你完全可以依赖这个回调来确认所有存储已就绪,后续的记录添加操作直接放在这里或者createDatabase()的then回调中即可。
如果需要在升级事务完成时就得到通知(比如写入初始化数据),可以直接监听全局升级事务的oncomplete事件,修改后的代码如下:
function createDatabase() { return new Promise((resolve, reject) => { const dbOpenRequest = window.indexedDB.open('GHCaching', 14); dbOpenRequest.onupgradeneeded = (event: any) => { const db = event.target.result; // 获取全局升级事务 const upgradeTransaction = event.target.transaction; // 按需创建对象存储 if (!db.objectStoreNames.contains('myTestStore1')) { db.createObjectStore('myTestStore1', { keyPath: 'ssn' }); } if (!db.objectStoreNames.contains('myTestStore2')) { db.createObjectStore('myTestStore2', { keyPath: 'ssn' }); } // 监听整个升级事务完成 upgradeTransaction.oncomplete = () => { console.log('所有对象存储创建完成'); }; }; dbOpenRequest.onsuccess = (event: any) => { const db = event.target.result; console.log('数据库打开成功,所有对象存储已就绪'); resolve(db); // 建议返回db实例,方便后续直接操作 }; dbOpenRequest.onerror = (event: any) => { console.error('创建数据库出错:', event.target.error); reject(event.target.error); }; }); }
关键注意事项
- 每次修改数据库结构(新增存储、修改索引等),必须提升版本号(比如从14改为15),否则
onupgradeneeded不会触发 - 检查
db.objectStoreNames.contains是必要的,避免重复创建对象存储导致报错 - 后续的业务操作(如添加记录),直接在
createDatabase().then(db => { /* 这里操作db */ })中执行即可,此时所有存储都已完全就绪
内容的提问来源于stack exchange,提问作者David Mason
相关产品推荐
相关产品推荐

