2016-10-28 8 views
1

An dieser Linie:IndexedDB: TransactionInactiveError

var request = store.add(obj); 

ich den Fehler:

TransactionInactiveError: A request was placed against a transaction which is currently not active, or which is finished.

ich nur die Fehlermeldung erhalten, wenn ich AJAX verwenden. Wie stelle ich sicher, dass der AJAX abgeschlossen wird, bevor die Transaktion abgeschlossen ist? Ich versuche, Informationen aus einer SQL-Datenbank in den Objektspeicher zu laden. Wenn ich den Fehler gegoogelt habe, bekomme ich Informationen über Transaktionen und die asynchrone Natur, aber ich habe keine konkrete Lösung mit Code gefunden.

Ich habe Rückrufe, Versprechungen und Timeouts untersucht (was sich für mich wie ein Hack anfühlt), aber ich kann diesen asynchronen Anruf nicht zur Arbeit bringen. Jede Hilfe würde sehr geschätzt werden.

var req = indexedDB.open(DB_NAME, DB_VERSION); 
req.onsuccess = function() { 
     db = this.result; 
     var tx = db.transaction('tblFields', 'readwrite'); 
     var store = tx.objectStore('tblFields'); 

      $.ajax({ 
        type: "POST", 
        url: "Off.aspx/GetFields", 
        data: '{}', 
        contentType: "application/json; charset=utf-8", 
        dataType: "json", 
        success: function (response) { 
         var customers = response.d; 
         $(customers).each(function() { 
          var obj = { measureID: this.measureID, measureName: this.measureName, fieldName: this.fieldName }; 
          var request = store.add(obj); 
         }); 
        }, 
        failure: function (response) { 
         alert(response.d); 
        }, 
        error: function (response) { 
         alert(response.d); 
        } 
       }); 
} 

Antwort

1

Ihr Erfolgsrückruf wird asynchron ausgeführt. Das Verschieben der Transaktion Initialisierungscode in den Rückruf sollte das Problem beheben:

success: function (response) { 
    var customers = response.d; 
    var tx = db.transaction('tblFields', 'readwrite'); 
    var store = tx.objectStore('tblFields'); 
    $(customers).each(function() { 
     var obj = { measureID: this.measureID, measureName: this.measureName, fieldName: this.fieldName }; 
     var request = store.add(obj); 
    }); 
}, 
0

Wenn IndexedDB keine aktiven Anforderungen an einer Transaktion erkennt es nach kurzer Zeit geschlossen wird. Wenn Sie eine Ajax-Anfrage machen, erhält diese nicht sofort eine Antwort. Zwischen dem Zeitpunkt, an dem Sie die Ajax-Anforderung stellen und eine Antwort erhalten, sieht IDB keine aktiven IDB-Anforderungen, die die Transaktion verwenden, sodass die Transaktion geschlossen wird.

Die Lösung ist einfach. Führen Sie zuerst die Ajax-Anfrage durch und dann die IDB-Transaktion. Hier einige Pseudo-Code:

$.ajax({ 
    success: function(response) { 
    var req = indexedDB.open(...); 
    req.onsuccess = function(event) { 
     var db = event.target.result; // or this.result, or req.result 
     var tx = db.transaction(...); 
     var store = tx.objectStore(...); 
     for(var customer of response.d) { 
     var obj = {...}; 
     store.add(obj); 
     } 
    }; 
    } 
}); 

Wenn Sie verspricht verwenden möchten, und haben Zugriff auf ES6, etwas zu tun, wie folgt aus:

function dbconnect(name, version, upgrade) { 
    return new Promise(function(resolve, reject) { 
    var request = indexedDB.open(name, version); 
    request.onupgradeneeded = upgrade; 
    request.onsuccess = function(event) { 
     var db = event.target.result; 
     resolve(db); 
    }; 
    request.onerror = function(event) { 
     var error = event.target.error; 
     reject(error); 
    }; 
    request.onblocked = function(event) { 
     console.warn('blocked, not fulfilling promise until unblocked'); 
    }; 
    }); 
} 

function ajaxpostrequest(url) { 
    return new Promise(function(resolve, reject) { 
    $.ajax({ 
     type: 'post', 
     data: '{}', 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json', 
     url: url, 
     success: resolve, 
     failure: reject, 
     error: reject 
    }); 
    }); 
} 

function addcustomer(db, customer) { 
    return new Promise(function(resolve, reject) { 
    var tx = db.transaction(...); 
    var store = tx.objectStore(...); 
    var obj = {measureId: customer.measureId, ...}; 
    var request = store.add(obj); 
    request.onsuccess = function(event) { 
     resolve(); 
    }; 
    request.onerror = function(event) { 
     reject(event.target.error); 
    }; 
    }); 
} 


async function request_then_connect_then_put() { 
    try { 
    var response = await fetch(url, {method:'post'}); 
    console.log('fetched url'); 
    var json = await response.json(); 
    var customers = json.d; 
    console.log('read json object from text of url'); 
    var db = await dbconnect(...); 
    console.log('connected to database', db.name); 
    var addpromises = customers.map((customer) => addcustomer(db, customer)); 
    var result = await Promise.all(addpromises); 
    console.log('stored all customer object things'); 
    } catch(error) { 
    console.debug(error); 
    } 
}