因此,对于我的周末项目,我选择学习 IndexedDB。我正在尝试创建类似 DAO 的东西(抱歉,这是我内心的 Java 开发人员)。这是我所拥有的:
function ReceiptDB() {
this.db = null;
this.dbname = "Receipts";
this.dbver = 2;
this.getDB = function() {
return db;
};
this.setDB = function(dbresult) {
db = dbresult;
};
var topThis = this;
this.initialize = function() {
alert("Running init");
var promise = $.Deferred();
var request = indexedDB.open(this.dbname, this.dbver);
request.onsuccess = function(e) {
topThis.db = e.target.result;
topThis.setDB(e.target.result);
promise.resolve();
};
request.onupgradeneeded = function(e) {
console.log("Upgrading database");
var db = event.target.result;
if (!db.objectStoreNames.contains("GroupIDs")) {
var groupIdObjectStore = db.createObjectStore("GroupIDs");
}
if (!db.objectStoreNames.contains("Locations")) {
var storesObjectStore = db.createObjectStore("Locations");
}
};
request.onfailure = function(e) {
alert("failed to open db");
//topThis.initPromise.reject();
promise.reject();
};
request.onerror = function(e) {
alert("init error: " + e.target.errorCode);
promise.reject();
};
return promise;
};
this.getAllGroupIds = function() {
var promise = $.Deferred();
var results = [];
var db = topThis.db;
if (!db) {
alert("DB not initialized!");
}
var tx = topThis.db.transaction("GroupIDs", "readonly");
var store = tx.objectStore("GroupIDs");
store.openCursor().onsuccess = function(e) {
var cursor = event.target.result;
if (cursor) {
results.push(cursor.value);
cursor.continue();
}
promise.resolve(results);
};
return promise;
};
this.init();
};
我使用 HTML 按钮触发此操作:
$(document).ready(function() {
$("#btn1").click(function(e) {
var receiptdb = new ReceiptDB();
var initPromise = receiptdb.initialize();
$.when(initPromise).done(function() {
console.log("receiptdb promise done");
var getAllPromise = receiptdb.getAllGroupIds();
});
});
}
我使用 promise 来确保对象在我尝试对数据库运行查询之前初始化数据库。不幸的是,它不起作用:当我调用 getAllGroupIds() 方法时,数据库为空。对我来说,这应该通过 init 方法来处理。
谁能告诉我哪里出错了?
编辑:我将 init 函数重命名为initialize() 并手动调用它,因为构造函数调用值没有什么意义。 杰森
编辑 2:在看到 Josh 回答之前,我改变了态度。不过,我仍然使用 Promise。
function openDatabase(DBNAME, DBVER) {
var promise = $.Deferred();
var request = window.indexedDB.open(DBNAME, DBVER);
request.onsuccess = function(e) {
console.log("Successfully opened DB");
promise.resolve(e.target.result);
};
request.onupgradeneeded = function(e) {
console.log("configuring database");
// create datastores and indexes
};
request.onfailure = function(e) {
promise.reject();
};
request.onerror = function(e) {
console.log("Error opening database: " + e.target.errorCode);
promise.reject();
};
}
此时,只要 promise 得到解决,我就可以创建一个存储库:
function Repository(database) {
this.db = database;
this.get = function(id) {
// get an item by id, return a promise (again) since the
// result is inside another onsuccess callback
}
// rest of crud functions
}
var dbPromise = openDatabase("mydb", 1);
$.when(dbPromise).done(function(db) {
var repo = new Repository(db);
var resultPromise = repo.get(id);
$.when(resultPromise).done(function(result)) {
// do something with the result
};
});
我不太喜欢嵌套的 $.when ,但它似乎对我有用
最佳答案
首先猜测,是当您将 e.target.result 分配给 topThis.db 时。您将一个仅保证在其范围或依赖范围内有效的值分配给独立的外部范围。
我建议在继续之前花一些时间学习如何编写异步 js。另外,我个人建议避免做出 promise ,因为考虑到您所遇到的问题的性质,您实际上所做的一切只是增加了问题的复杂性,甚至掩盖了问题。
简单地说,不要引用全局 db 变量来响应 onclick,而是打开一个新连接。接下来,将其作为第一个参数传递给其他函数。另外,与编写异步代码相关,不要尝试编写返回值的函数,而是编写将结果传递给回调函数的函数。
要开始使用,请确保您了解以下内容:
var x;
function setOuterX() {
x = 'Hello World';
}
setTimeout(setOuterX, 0);
console.log(x);
关于javascript - 索引数据库 : Database Not Initialized,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37635558/