使用IndexedDB,似乎已经创建了一个读取和显示数据的事务,似乎无法在我的对象存储中创建第二个事务(只是ToDo的列表)。在尝试创建第二个事务的行上没有出现错误,但是什么也没有发生,并且代码停止了执行。
检索和显示我的数据的这一部分运行正常:
var trans;
var ostore;
var db;
var reqdb = window.indexedDB.open("ToDoApp", 2);
reqdb.onupgradeneeded = function (event) {
console.log("running onupgradeneeded");
var myDB = event.target.result;
if (!myDB.objectStoreNames.contains("todos")) {
myDB.createObjectStore("todos", { keyPath: "ToDoTitle" });
}
};
reqdb.onsuccess = function (event) {
db = event.target.result;
trans = db.transaction(["todos"], "readonly");
ostore = trans.objectStore("todos");
var req = ostore.get("TEST IDB 2");
$("#btnSave").click(function () {
UpdateToDo();
});
req.onerror = function (event) {
alert("error");
};
req.onsuccess = function (event) {
$("#ToDoTitle").val(req.result.ToDoTitle);
};
};
这可以显示一切。但是请注意,通过onclick事件设置的UpdateToDo()函数使我可以实际更新数据。
function UpdateToDo(event) {
alert("1");
var newtransaction = db.transaction(["todos"], "readwrite");
alert("2");
var newstore = newtransaction.objectStore("todos");
newstore.openCursor().onsuccess = function (event) {
const cursor = event.target.result;
if (cursor) {
if (cursor.value.ToDoTitle == 'TEST IDB 2') {
const updateData = cursor.value;
updateData.ToDoCategory = 1; // hard coding for now
var requpdate = cursor.update(updateData);
requpdate.onsuccess = function () {
console.log('Updated');
};
requpdate.onerror = function () {
console.log('Error');
}
};
cursor.continue();
} else {
console.log('Cursor error.');
}
};
}
第一个警报会触发,但第二个警报不会触发。我以为是因为返回了创建第一个事务的第一个回调,所以该事务已关闭,但是它似乎仍然阻止我创建该事务。如果我完全完成第一个事务,则创建第二个事务,并运行第二个警报...然后,从那里我可以创建一个游标并更新数据。
我尝试使第一个事务和对象存储作为全局变量,但这也不起作用。
只让您每页执行一次事务似乎有些荒谬。我还应该如何初始加载数据,然后允许用户对其进行更新?我想念什么吗?
答案 0 :(得分:2)
几点:
alert
与indexdDb调用一起使用。 indexedDB是异步的。 alert
不是异步的,它在显示时暂停执行,这可能导致某些奇怪的行为。最好使用console.log,因为这样不会停止执行。IDBObjectStore.prototype.get
代替openCursor
例如,以下是一些上述建议的伪代码:
function connect(name, version, upgrade) {
return new Promise((resolve, reject) => {
var req = indexedDB.open(name, version);
req.onupgradeneeded = upgrade;
req.onsuccess = event => resolve(req.result);
req.onerror = event => reject(req.error);
});
}
function onupgradeneeded(event) {
var db = event.target.result;
db.createObjectStore(...);
}
function updateTodo(db, todo) {
return new Promise((resolve, reject) => {
var tx = db.transaction('todos', 'readwrite');
tx.onerror = event => reject(event.target.error);
tx.oncomplete = resolve;
var store = tx.objectStore('todos');
var req = store.get(todo.title);
req.onsuccess = event => {
// When using get instead of openCursor, we just grab the result
var old = event.target.result;
// If we are updating we expect the current db value to exist
// Do not confuse a get request succeeding with it actually matching
// something. onsuccess just means completed without error.
if(!old) {
const error = new Error('Cannot find todo to update with title ' + todo.title);
reject(error);
return;
}
// Change old todo object props
old.category = todo.category;
old.foo = todo.bar;
// Replace old with a newer version of itself
store.put(old);
};
});
}
function onpageloadInitStuff() {
mybutton.onclick = handleClick;
}
async function handleClick(event) {
var db;
try {
db = await connect('tododb', 1, upgradeneededfunc);
var newtodo = todolist.querySelector('todolist[checked]');
await updateTodo(db, newTodo);
} catch(error) {
alert(error); // it is ok to alert here, still better to console.log though
} finally {
if(db) {
db.close();
}
}
}
答案 1 :(得分:1)
伊斯坎达和我在同一时间有相同的想法。在UpdateToDo函数中,我打开了与IndexedDB实例的完全独立的连接,并使新的事务/存储连接到该实例。.处理该请求有效
function UpdateToDo() {
var udb = window.indexedDB.open("ToDoApp", 2);
alert("1");
udb.onsuccess = function (event) {
alert("2");
db2 = event.target.result;
var trans2 = db2.transaction(["todos"], "readwrite");
var ostore2 = trans2.objectStore("todos");
alert("3");
var blabla = ostore2.openCursor();
blabla.onsuccess = function (event2) {
来自MS Sql Server / ASP.NET背景,打开与同一个DB的多个连接感觉很直观。
直到去年,IndexedDB和Cache API似乎在Safari上才真正稳定,直到去年(2018年),服务人员才完全没有包含在Safari中。尽管Android拥有全球市场,但在北美,如果Apple不支持Android,则不会有太多的发展……它解释了这些新功能的最后文档和教程。祝大家好运