IndexedDB when populating many ObjectStores, Error: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running
IndexedDB when populating many ObjectStores, Error: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running
@Josh 已经回答了一个关于填充 IndexedDB ObjectStores 时的错误消息的类似问题:
Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running
答案适用于只填充一个 ObjectStore 的情况。但是就我而言,我需要填充至少 5 个 ObjectStores。
我可以通过遍历一个列表来创建和填充所有 ObjectStores,该列表包含创建和填充每个对象存储所需的所有数据。该脚本大部分时间都运行良好,但是我检测到一个缺陷,所以每次都执行而不是完美运行,在执行一些执行后我收到上述消息。
如答案中所述,问题与执行时间有关。根据发布的解决方案,我修改了我的代码,以便在创建和填充的所有过程中使用相同的事务。但是执行的时候又出现了新的错误:
Uncaught TransactionInactiveError: Failed to execute 'put' on 'IDBObjectStore': The transaction has finished.
@Josh 又是解决问题的人。
我如何才能完美地填充最近创建的 ObjectStores,而不会出现之前的任何错误?这是代码:
var db;
function createPopulate(DB_NAME, DB_VERSION) {
const datastores = [
{osName:'a', osEndpoint:'/a', osKeyPath:'id',....},
{osName:'b', osEndpoint:'/b', osKeyPath:'id',....},
{osName:'c', osEndpoint:'/c', osKeyPath:'id',....}
];
var request = indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = function(e) {
db = this.result;
var tx = e.target.transaction;
for (i in datastores) {
// ObjectoStore created
// Index created
var customObjectStore = tx.objectStore(datastores[i].osName, "readwrite");
popTable(customObjectStore, datastores[i].osEndpoint);
}
};
函数内部,有popTable函数,获取数据并填充给定的ObjectStore,使用fetch函数,fetch API:
function poptable(parameter, endPoint)
fetchGet2(endPoint, populate, parameter);
function populate(json, parameter) {
for (var m in json) {
parameter.add(json[m]);
}
}
}
当运行代码时,我收到这条消息:
DOMException: Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.
如果脚本被修改为只执行popTable oncomplete事件,错误信息为:
DOMException: Failed to execute 'objectStore' on 'IDBTransaction': The transaction has finished. at IDBTransaction.objectStore.transaction.oncomplete.
如何避免这些错误?
您不能在等待其他异步事件发生时保持事务打开,这就是您在 fetchGet2
中所做的事情。只要所有请求都完成,事务就会自动提交,这基本上意味着如果您有一个请求,您在打开事务后没有同步发出 或 在其中一个请求的事件处理程序中发出(可以任意嵌套),那么您的事务将在该请求执行之前提交。
您要么必须在向 IndexedDB 写入任何内容之前完成所有数据提取,要么必须为每次提取使用单独的事务。
@Josh 已经回答了一个关于填充 IndexedDB ObjectStores 时的错误消息的类似问题:
Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running
答案适用于只填充一个 ObjectStore 的情况。但是就我而言,我需要填充至少 5 个 ObjectStores。
我可以通过遍历一个列表来创建和填充所有 ObjectStores,该列表包含创建和填充每个对象存储所需的所有数据。该脚本大部分时间都运行良好,但是我检测到一个缺陷,所以每次都执行而不是完美运行,在执行一些执行后我收到上述消息。
如答案中所述,问题与执行时间有关。根据发布的解决方案,我修改了我的代码,以便在创建和填充的所有过程中使用相同的事务。但是执行的时候又出现了新的错误:
Uncaught TransactionInactiveError: Failed to execute 'put' on 'IDBObjectStore': The transaction has finished.
@Josh 又是解决问题的人。
我如何才能完美地填充最近创建的 ObjectStores,而不会出现之前的任何错误?这是代码:
var db;
function createPopulate(DB_NAME, DB_VERSION) {
const datastores = [
{osName:'a', osEndpoint:'/a', osKeyPath:'id',....},
{osName:'b', osEndpoint:'/b', osKeyPath:'id',....},
{osName:'c', osEndpoint:'/c', osKeyPath:'id',....}
];
var request = indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = function(e) {
db = this.result;
var tx = e.target.transaction;
for (i in datastores) {
// ObjectoStore created
// Index created
var customObjectStore = tx.objectStore(datastores[i].osName, "readwrite");
popTable(customObjectStore, datastores[i].osEndpoint);
}
};
函数内部,有popTable函数,获取数据并填充给定的ObjectStore,使用fetch函数,fetch API:
function poptable(parameter, endPoint)
fetchGet2(endPoint, populate, parameter);
function populate(json, parameter) {
for (var m in json) {
parameter.add(json[m]);
}
}
}
当运行代码时,我收到这条消息:
DOMException: Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.
如果脚本被修改为只执行popTable oncomplete事件,错误信息为:
DOMException: Failed to execute 'objectStore' on 'IDBTransaction': The transaction has finished. at IDBTransaction.objectStore.transaction.oncomplete.
如何避免这些错误?
您不能在等待其他异步事件发生时保持事务打开,这就是您在 fetchGet2
中所做的事情。只要所有请求都完成,事务就会自动提交,这基本上意味着如果您有一个请求,您在打开事务后没有同步发出 或 在其中一个请求的事件处理程序中发出(可以任意嵌套),那么您的事务将在该请求执行之前提交。
您要么必须在向 IndexedDB 写入任何内容之前完成所有数据提取,要么必须为每次提取使用单独的事务。