TransactionInactiveError以及后续的put调用

时间:2015-03-21 18:28:24

标签: javascript cordova indexeddb

我无法弄清楚我是做错了什么,还是我只是努力推动它。

我正在尝试将来自我的在线数据库的约70000条记录与IndexedDBEventSource同步到Worker

所以每个包获得2000条记录,然后使用以下代码将它们存储在IndexedDB中:

eventSource.addEventListener('package', function(e) {
    var data = JSON.parse(e.data);

    putData(data.type, data.records);
});

function putData(storeName, data) {
    var store = db.transaction([storeName], 'readwrite').objectStore(storeName);

    return new Promise(function(resolve, reject) {
        putRecord(data, store, 0);

        store.transaction.oncomplete = resolve;
        store.transaction.onerror = reject;
    });
}

function putRecord(data, store, recordIndex) {
    if(recordIndex < data.length){
        var req = store.put(data[recordIndex]);

        req.onsuccess = function(e) {
            recordIndex += 1;
            putRecord(data, store, recordIndex);
        };
        req.onerror = function() {
            self.postMessage(this.error.name);
            recordIndex += 1;
            putRecord(data, store, recordIndex);
        };
    }
} 

一切都适用于约10000条记录。没有真正测试限制在哪里。我怀疑在某些时候,并行的事务太多会导致单个事务非常慢,从而因为某些超时而导致问题。根据开发工具,70000记录约为20MB。

完成错误:

  

未捕获的TransactionInactiveError:无法执行'put'   'IDBObjectStore':交易已经完成。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我没有在代码中看到明显的错误,但您可以使其更简单,更快捷。我们无需等待上一个put()成功发出第二个put()请求。

function putData(storeName, data) {   
    var store = db.transaction([storeName], 'readwrite').objectStore(storeName);

    return new Promise(function(resolve, reject) {
        for (var i = 0; i < data.length; ++i) {
            var req = store.put(data[i]);
            req.onerror = function(e) {
                self.postMessage(e.target.error.name);
            };            
        }

        store.transaction.oncomplete = resolve;
        store.transaction.onerror = reject;
    });
}

可能您看到的错误是因为浏览器对事务实施了任意时间限制。但同样,你的代码看起来是正确的,包括使用Promises(这对IDB来说很棘手,但据我所知,你能正确地做到这一点!)

如果仍然发生这种情况,我会在评论中使用独立的repro对浏览器提交错误。 (如果它在Chrome中发生,我很乐意看看。)

答案 1 :(得分:0)

我认为这是由于实施。如果您阅读规范,则事务必须保留事务中所有请求的列表。提交事务时,所有这些更改都会保留,否则事务将被中止。 Specs

可能是您的情况下1000请求的最大请求列表。您可以通过尝试插入1001条记录来轻松测试。所以我的猜测是,当达到1000请求时,事务被设置为不活动。

也许改变你的策略,只在每笔交易中提出1000个请求,并在完成另一个交易时开始新的交易。