异步indexeddb

时间:2016-02-24 16:55:27

标签: javascript asynchronous indexeddb

我想在indexeddb的异步模式下做一些事情而且我失败了。你对我的问题有所了解吗?

代码:

function test(basekey) {
    window.indexedDB.deleteDatabase("base");

    var lConnection = window.indexedDB.open("base", 1);
    lConnection.onsuccess = function (event) {
        var lDB = event.target.result;
        var lTransactionGlobal = lDB.transaction(['person'], 'readwrite');
        var lTransactionTable = lTransactionGlobal.objectStore('person');
        var lRequest = lTransactionTable.add({key: basekey+1, name:"me"});
        lRequest.onsuccess = function (e) {
            window.setTimeout(function () {
                console.log("Second wrote");
                lRequest = lTransactionTable.add({key: basekey+2, name:"you"});
                lRequest.onsuccess = function () {
                    lDB.close();
                };
                lRequest.onerror = function () {
                    console.error("Request 2 failed");
                };
            }, 0);
        };
        lRequest.onerror = function () {
            console.error("Request 1 failed");
        };
    };
    lConnection.onblocked = function () { console.log("Blocked"); };
    lConnection.onerror = function () { console.log("Error"); };
    lConnection.onupgradeneeded = function (pEvent) {
        var db = pEvent.target.result;
        var objectStore = db.createObjectStore("person", { keyPath: "key" });
    };
}

当我调用test(0)时,第二次“添加”时出现此错误:

  

未捕获的TransactionInactiveError:无法在“IDBObjectStore”上执行“添加”:事务已完成。

我尝试过使用Firefox和Chrome。

1 个答案:

答案 0 :(得分:3)

这是索引数据库的设计点:当事务没有进一步处理请求时,事务会立即尝试提交。可以在创建后直接对事务进行请求,也可以在来自该事务中先前请求的事件的处理程序中进行请求。所以你不能在public ArrayList<String> getFile(File dir) { File listFile[] = dir.listFiles(); if (listFile != null && listFile.length > 0) { for (File file : listFile) { if (file.isDirectory()) { getFile(file); } else { if (file.getName().endsWith(".png") || file.getName().endsWith(".jpg") || file.getName().endsWith(".jpeg") || file.getName().endsWith(".gif") || file.getName().endsWith(".bmp") || file.getName().endsWith(".webp")) { String temp = file.getPath().substring(0, file.getPath().lastIndexOf('/')); if (!fileList.contains(temp)) fileList.add(temp); } } } } return fileList; } 回调中做出进一步的请求,因为(1)它不是来自请求的事件处理程序,(2)在你调用setTimeout()之后没有进一步的工作并且事务将开始试图提交。

这是一个简化的例子,数字表示事物的执行顺序。

setTimeout()

这说明了两种情况:事务在function myFunc(connection) { var tx = connection.transaction('store'); // (1) transaction is "active" here, you can make requests. var store = tx.objectStore('store'); store.get('key1').onsuccess = function() { // (3) transaction is "active" again here. store.get('key2').onsuccess = function() { // (5) transaction is also "active" here. setTimeout(function() { // (7) transaction is "inactive" here, and the // transaction will have attempted to commit, // so this will fail. store.get('key3'); // WILL THROW }, 0); // (6) transaction will be "inactive" when this returns. // Since there are no more pending requests it will attempt // to commit. }; // (4) transaction will be "inactive" when this returns. }; // (2) transaction will become "inactive" when control // returns to the event loop here. } 回调中不活动,并且在事务开始提交之后仍然存在。但是你会分别看到与第一种情况相同的行为 - 例如如果你有一个长期运行的交易(大量的异步请求)并尝试在setTimeout()中做一些事情,即使有未完成的交易,例如在(3)之后移动setTimeout()

您必须先将工作分解为多个事务,或者首先执行所有非IDB异步工作。