超出最大 IPC 消息大小

Maximum IPC message size exceeded

目前,我正在网络浏览器上开发工具 运行。

在这个项目中,我使用 IndexedDB 和 Dexie.js 版本 2.x。

在 Google Chrome 上,我提到了错误 "Maximum IPC message size exceeded"。估计是IndexedDB里面放了这么大的数据造成的。 我的临时实现是通过JSON.stringify将数组转换为字符串,我曾经实现过这个问题。然而,问题又出现了。

我的问题是...

  1. 如何避免这个错误?
  2. 我想拯救存储在 IndexedDB 中的数据。我知道数据存储在本地文件系统中的什么位置。如果可以的话,怎么做?

如果您查看 Chrome 实现中导致此错误的原因,例如 https://chromium.googlesource.com/chromium/src.git/+/master/content/browser/indexed_db/indexed_db_database.cc,当消息大小过大时会发生此错误。这里的消息大小基本上是指作为某些处理的结果从 C++(浏览器二进制文件)发送到 Javascript 的数据量。

为避免发送过多数据,您可以执行以下操作:

  • 确保您永远不会对大量数据调用 getAll
  • 在对潜在大量数据调用 getAll 时使用限制
  • 使用 openCursor 而不是 getAll
  • 存储较小的对象

我认为最好的办法是尝试切换到 openCursor。这将一次取回您的物品(根据请求)。这样你就可以避免 运行 进入这个错误。使用游标会稍微降低速度,但会获得可伸缩性。

要像 getAll 一样使用游标,很简单。您需要做的就是首先声明一个空数组,然后启动游标,并迭代,每次将游标项添加到数组中。在迭代结束时,您基本上一次从一个片段中组装出与调用 getAll 相同的数组结果。

如果你在一些大数据集上使用Dexie的toArray()方法,尝试用offset(number)limit(number)限制记录数,以批量获取数据

我找不到类似游标的方式来使用 Dexie 进行查询(可能看起来不够难),但我想继续使用 Dexie 作为我的抽象层。

我需要检索所有记录并根据 ID 检索一个子集(与您相同),我想到了以下解决了我们的问题:

/**
 * Retrieve all of Dexie collection
 *
 * We can't just call Collection.toArray() because once the result is large
 * enough, we'll get "Maximum IPC message size exceeded" error. This is a
 * memory-friendly implementation. Although maybe a bit slow due to a page
 * size of one.
 */
function retrieveDexieCollection(collection) {
  return new Promise(async (resolve, reject) => {
    try {
      const result = []
      await collection.each(r => {
        result.push(r)
      })
      return resolve(result)
    } catch (err) {
      return reject(err)
    }
  })
}

// then later, use our function
const projectIds = [1,2,3]
const records = await retrieveDexieCollection(db
  .whateverYourTableIsCalled
  .where('projectId')
  .anyOf(projectIds))

如果您需要随时处理记录(我就是这样做的),您可以添加一个 mappingFunction 参数并在将每个元素添加到数组之前调用它。

该函数非常灵活,因为您可以将任何 Dexie 集合传递给它;整个 table 或任意查询的结果。