2016-02-24 5 views
-1

Я хочу сделать что-то в асинхронном режиме с индексированнымdb и я терпеть неудачу. У вас есть идея по моей проблеме?Asynchronous 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" }); 
    }; 
} 

Когда я называю тест (0) Я эту ошибку для второго "добавить":

Uncaught TransactionInactiveError: Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.

Я попытался с Firefox и Chrome.

ответ

3

Это точка проектирования индексированной БД: транзакции совершаются немедленно, когда у них нет дальнейших запросов на обработку. Запросы могут быть сделаны против транзакции непосредственно после создания или в обработчике события из предыдущего запроса в этой транзакции. Таким образом, вы не можете запрашивать дополнительные запросы в обратном вызове setTimeout(), потому что (1) это не обработчик событий из запроса и (2) после того, как вы вызываете 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() обратного вызова, и это после того, как сделка начала совершать в любом случае. Но вы увидите одно и то же поведение с первым случаем отдельно - например. если у вас длительная транзакция (много асинхронных запросов), и попытайтесь сделать что-то в setTimeout(), даже если есть незавершенные транзакции, например. перемещая setTimeout() сразу после (3).

Вы должны разбить свою работу на несколько транзакций или выполнить всю работу с асинхронным IDB.

+0

Я боялся этого ответа ... Хорошо, спасибо за ваше подтверждение :( – Chklang