尝试使用相同的读写事务。看起来您在两个地方调用 db.transaction(...) 。然后,您尝试在不同事务的上下文中更新链接到不同事务的对象存储。结果是其中一个事务完成(其生命周期结束),可能是因为它超时了,因为它没有检测到任何已注册的请求。 objectStore 变量存在于提前完成的事务的生命周期内,因此您会收到事务完成错误。
这很容易解决。您只需要在其生命周期结束之前在同一事务上注册一个新请求(put 请求)。为此,您可以 (a) 内联语句 request = getObjectStoreClienteDB("name",valor); 以便它附加到同一个事务实例,或者 (b) 将事务实例存储在单独的变量中并在两个调用中引用它。
例如,以下代码是对您使用单个事务的修改:
// this function was changed, it now takes an active transaction as its first argument.
function getObjectStoreClienteDB(transaction, clave,valor){
//Ahora recogeremos los datos de nuestro almacén "Productos"
// this was changed. instead of creating a new transaction we just reference the
// transaction instance passed to this function
var objectStore = transaction.objectStore("customers");
var index = objectStore.index(clave);
var singleKeyRange = IDBKeyRange.only(valor);
// To use one of the key ranges, pass it in as the first argument of openCursor()/openKeyCursor()
return index.openCursor(singleKeyRange);
}
function updateClienteDB(clave,valor,newvalor){
console.log("updateClienteDB ... clave: "+clave+" valor: "+valor+" newvalor: "+newvalor);
// this line was added. we create the transaction here, once
var transaction = db.transaction(["customers"], "readwrite");
// this line was changed, we simply reference the transaction instance here instead of
// creating a second transaction
var objectStore = transaction.objectStore("customers");
// this line was changed, we pass in the one active transaction instance to the function
// now instead of having the function create its own transaction
request = getObjectStoreClienteDB(transaction, "name",valor);
request.onsuccess = function(event) {
// Get the old value that we want to update
var data = request.result;
// update the value(s) in the object that you want to change
if(clave=="name")
data.name = newvalor;
else if(clave=="email")
data.email = newvalor;
else if(clave=="matricula")
data.matricula = newvalor;
else if(clave=="telefono")
data.telefono = newvalor;
// Put this updated object back into the database.
// this line now works. objectStore is attached to our 1 transaction that is still 'alive'
// because it gets registered 'in time' (before transaction finishes due to timeout due
// to no additional requests registered in allowed time window).
var requestUpdate = objectStore.put(data);
requestUpdate.onerror = function(event) {
console.log("addCliente ..."+name+" "+email +" "+ event.target.errorCode);
};
requestUpdate.onsuccess = function(event) {
console.log("All done!");
};
};
}
而且,为了清楚起见,这里是第二个例子。它使用调用者的事务重新创建对对象存储的引用,而不是交叉引用附加到不同事务的对象存储:
function updateClienteDB(clave,valor,newvalor){
console.log("updateClienteDB ... clave: "+clave+" valor: "+valor+" newvalor: "+newvalor);
var objectStore = db.transaction(["customers"], "readwrite").objectStore("customers");
request = getObjectStoreClienteDB("name",valor);
request.onsuccess = function(event) {
// Get the old value that we want to update
var data = request.result;
// update the value(s) in the object that you want to change
if(clave=="name")
data.name = newvalor;
else if(clave=="email")
data.email = newvalor;
else if(clave=="matricula")
data.matricula = newvalor;
else if(clave=="telefono")
data.telefono = newvalor;
// Put this updated object back into the database.
// the following line is changed so that it works.
//var requestUpdate = objectStore.put(data);
var theOtherTransactionThatIsStillAlive = event.transaction;
var objectStoreFromValidTransaction = theOtherTransactionThatIsStillAlive.objectStore('customers');
var requestUpdate = objectStoreFromValidTransaction.put(data);
requestUpdate.onerror = function(event) {
console.log("addCliente ..."+name+" "+email +" "+ event.target.errorCode);
};
requestUpdate.onsuccess = function(event) {
console.log("All done!");
};
};
}