【问题标题】:TransactionInactiveError with subsequent put calls带有后续 put 调用的 TransactionInactiveError
【发布时间】:2015-03-21 18:28:24
【问题描述】:

我不知道我做错了什么,或者我只是在努力。

我正在尝试将 ~70000 条记录从我的在线数据库同步到 IndexedDB 以及 EventSourceWorker

所以我每个包有 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:无法执行“放置” 'IDBObjectStore': 事务已完成。

有什么想法吗?

【问题讨论】:

标签: javascript cordova indexeddb


【解决方案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 来说很棘手,但据我所知,您做得正确!)

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 我认为它与请求的数量没有直接关系。据我所知,请求没有真正的限制,尽管可能会使用内存。每笔交易我可以远远超过 1000 或 2000 个请求。我的代码也适用于 30 笔交易,然后其中一项最终失败。
    • 也许尝试限制事务中的请求数。正如规范所说:交易预计是短暂的。自动提交功能鼓励这样做。作者仍然可以导致交易长时间运行;但是,通常不推荐这种使用模式,因为它会导致糟糕的用户体验。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-17
    • 2018-12-30
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 2018-03-02
    相关资源
    最近更新 更多