You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:12:42