indexed DB使用分析和问题排查

572 阅读3分钟

在indexedDB使用的时候可能会遇到 Failed to execute 'transaction' on 'IDBDatabase': One of the specified object stores was not found 这种问题。我们从 indexed DB 的使用来分析可能原因,一些封装的包暴露的接口可能不同但是大体思路是一致的。急性子同学的传送门

使用步骤

indexed DB 可以类比数据库的使用,为什么要牵扯数据库呢,因为上面的问题是可以映射到数据库连接过程中的一些问题。我们从 indexed DB 的使用步骤开始说:

      // ********************* 步骤一 *********************
const dbConnection = indexedDB.open("test DB name", 1); // 打开db名称,第二个参数是版本号

      // ********************* 步骤四 *********************
dbConnection.addEventListener("success", (event) => {
  // 在success事件中,回调的result就是db实例
  const dbInstance = event.target.result;

      // ********************* 步骤五 *********************
  // 创建数据库事务
  const transaction = dbInstance.transaction(
    "table name", // 数据库表名
    "readwrite" // 当前事务的读写权限
  );

  const storeIndex = transaction.objectStore(); // 获取表的索引信息,用于读写

  const postData = {
    // 更新数据。这里需要把必填数据都填上,否则会报错而且提示语不明显
    id: "1",
    first: "column 1",
    second: "column 2",
  };

  const writeConnection = storeIndex.put(postData); // 写数据,自动提交事务

  writeConnection.onsuccess = (event) => {
    // 异步完成
  };

  writeConnection.onerror = (event) => {
    // 异步报错
  };
});

      // ********************* 步骤二 *********************
// 处理:DB配置升级(和第一行的DB版本号有关),DB初始化(第一次打开没有数据库)相关操作
dbConnection.addEventListener("upgradeneeded", (event) => {
  const db = event.target.result;

  // 当前indexedDB中不包含某个DB名,需要创建
  if (!db.objectStoreNames.contains("store name")) {
  
      // ********************* 步骤三 *********************
    const store = db.createObjectStore("store name", { // 创建DB
      keyPath: "id", // 主键
    });

    store.createIndex("first", "first", { // 列配置
      unique: true, // 不允许重复
    });

    store.createIndex("second", "second", { // 列配置
      unique: false, // 允许重复
    });
  }
});

根据上面注释中的步骤,先理一下执行顺序:

  1. 打开对应的 DB 以及指定版本。每次修改 DB 的表配置时,都需要升级版本号,否则升级配置不生效
  2. 监听 upgradeneeded 事件,DB表结构改变或者初次使用都需要在这个事件里面处理
  3. upgradeneeded 事件中,定义升级时如何处理对应的表结构
  4. 监听 success 事件,获取 DB 实例
  5. success 事件中,根据 DB 实例,创建事务,读写 DB

问题原因

Failed to execute 'transaction' on 'IDBDatabase': One of the specified object stores was not found 是 DB 中某一个表连接找不到了。有以下几种情况:

  1. DB 没有创建
  2. 创建后,DB 连接版本没有升级

可以用这几种情况检查:

  1. 检查 DB 版本。如果每一个版本的 DB 的表结构不同,在连接的时候发现表结构不存在,但是代码没什么问题,那么很有可能是在连接的时候的版本和定义对应表信息不同。一种典型表现是换一个浏览器就没这个问题 🤔 image.png

这种情况下将上面代码的第一步中的版本号修改成没有用过的版本号就可以了。为了让老用户的新功能也好用,尽量不要抱侥幸心理,换一个浏览器能用就可以。

  1. 展开 DB 表结构,检查要连接的表的列是否真的存在,或者是否有拼写错误。 image.png 这种情况需要在上面代码的第三步和第五步都进行检查:
  • 第三步检查在 DB 被删除的时候表被正常创建;
  • 第五步检查写入/读取的时候,是否涉及到不存在的列;