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

同一IndexedDB数据库并行创建多个store时的同步问题如何解决

IndexedDB 多ObjectStore同步创建失败解决方案

问题根因

  • IndexedDB 仅允许在upgradeneeded事件对应的versionchange事务中创建ObjectStore,该事务为自动提交类型:如果回调内存在异步操作间隙、或多次发起数据库版本升级请求分别创建不同store,都会导致只有首个store创建成功,后续操作执行时事务已提前关闭。
  • 高频错误场景包括:在数据库打开成功的success回调中创建store、在upgradeneeded回调中插入接口请求/定时器等异步逻辑后再创建剩余store、同时发起多个携带不同版本号的indexedDB.open请求分别创建store。

解决方案

方案1:单次版本升级批量创建所有固定store

如果所需的store列表是提前确定的,统一在upgradeneeded回调内同步完成所有store的创建,不要穿插非必要异步操作:

const DB_NAME = 'businessDB';
// 新增/删除store时必须提升版本号
const DB_VERSION = 3;
const dbRequest = indexedDB.open(DB_NAME, DB_VERSION);

dbRequest.onupgradeneeded = (event) => {
  const db = event.target.result;
  // 同步判断并创建所有需要的store
  if (!db.objectStoreNames.contains('userStore')) {
    db.createObjectStore('userStore', { keyPath: 'userId' });
  }
  if (!db.objectStoreNames.contains('goodsStore')) {
    db.createObjectStore('goodsStore', { keyPath: 'skuId' });
  }
  if (!db.objectStoreNames.contains('logStore')) {
    db.createObjectStore('logStore', { autoIncrement: true });
  }
};

dbRequest.onsuccess = (event) => {
  const db = event.target.result;
  // 此时所有store已创建完成可正常使用
  console.log('所有store创建完成,现有store列表:', db.objectStoreNames);
  db.close();
};

dbRequest.onerror = (event) => {
  console.error('数据库初始化失败:', event.target.error);
};

方案2:动态新增store时队列化批量处理

如果需要在业务运行过程中动态新增未知store,不要为每个store单独触发版本升级,而是维护待创建store队列,统一触发一次版本升级完成批量创建:

// 全局维护待创建store配置队列
const pendingCreateStores = [];
let activeDb = null;

// 新增store的统一调用方法
export function createStoreAsync(storeName, options = { keyPath: 'id' }) {
  return new Promise((resolve, reject) => {
    // 已存在的store直接返回
    if (activeDb?.objectStoreNames.contains(storeName)) {
      return resolve();
    }
    pendingCreateStores.push({ name: storeName, options });
    // 关闭已有连接才能触发版本升级
    if (activeDb) {
      activeDb.close();
    }
    // 读取当前最新版本号并+1触发升级
    const getVersionReq = indexedDB.open('businessDB');
    getVersionReq.onsuccess = (e) => {
      const currentVersion = e.target.result.version;
      e.target.result.close();
      const upgradeReq = indexedDB.open('businessDB', currentVersion + 1);
      
      upgradeReq.onupgradeneeded = (upgradeEvent) => {
        const db = upgradeEvent.target.result;
        // 批量创建所有队列内的store
        pendingCreateStores.forEach(config => {
          if (!db.objectStoreNames.contains(config.name)) {
            db.createObjectStore(config.name, config.options);
          }
        });
        pendingCreateStores.length = 0;
      };
      
      upgradeReq.onsuccess = (upgradeSuccessEvent) => {
        activeDb = upgradeSuccessEvent.target.result;
        resolve();
      };
      
      upgradeReq.onerror = (errEvent) => reject(errEvent.target.error);
    };
    getVersionReq.onerror = (errEvent) => reject(errEvent.target.error);
  });
}

注意事项

  • upgradeneeded回调内禁止执行非必要的异步操作,异步逻辑执行间隙versionchange事务会自动提交,后续创建store的操作会直接失效。
  • 同一时间不要发起多个indexedDB.open的版本升级请求,IndexedDB同一时间仅能处理一个versionchange事务,后续请求会被阻塞直到前一个数据库连接关闭。

内容的提问来源于stack exchange,提问作者Gonzagv

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 08:45:04