我对JS有一个很好的理解,但最终还是在学习。我正在尝试将一个PHP / mySQL项目重新创建到IndexedDB,并且无法解决为什么我在这里看到错误。
IndexedDB连接按预期工作。第一个函数(createItem)运行正常,但第二个函数(getItems)返回一个错误,声称“db”变量未定义。它是一个全局变量,因此应该可以通过函数的作用域访问,并且createItem函数使用它没有问题。任何人都可以帮我看看我错过了什么。
// GLOBAL DB VAR
var db;
// WAIT FOR DOM
document.addEventListener("DOMContentLoaded", function(){
// IF INDEXED DB CAPABLE
if("indexedDB" in window) {
// OPEN DB
var openRequest = indexedDB.open("newTabTest",1);
// CREATE NEW / UPDATE
openRequest.onupgradeneeded = function(e) {
// Notify user here: creating database (first time use)
var thisDB = e.target.result;
// Create "items" table if it doesn't already exist
if(!thisDB.objectStoreNames.contains("items")) {
var store = thisDB.createObjectStore("items", {keyPath: "id", autoIncrement: true});
store.createIndex("name","name", {unique:true});
store.createIndex("folder","folder", {unique:false});
store.createIndex("dial","dial", {unique:false});
}
}
openRequest.onsuccess = function(e) {
// Success- set db to target result.
db = e.target.result;
}
openRequest.onerror = function(e) {
// DB ERROR :-(
}
}
},false);
// CREATE ITEM FUNCTION
function createItem(n,u,f,c) {
var transaction = db.transaction(["items"],"readwrite");
var store = transaction.objectStore("items");
var item = {
name: n,
url: u,
folder: f,
colour: c,
dial: 0,
order: 100
}
var request = store.add(item);
request.onerror = function(e) {
console.log("An error occured.");
}
request.onsuccess = function(e) {
console.log("Successfully added.")
}
};
// GET ITEM(S) FUNCTION
// Specify index and key value OR omit for all
function getItems(callback, ind, key) {
var transaction = db.transaction(["items"],"readonly");
var store = transaction.objectStore("items");
var response = [];
// If args are omitted - grab all items
if(!ind | !key) {
var cursor = store.openCursor();
cursor.onsuccess = function(e) {
var res = e.target.result;
if(res) {
var r = {
"name": res.value['name'],
"url": res.value['url'],
"folder": res.value['folder'],
"colour": res.value['colour'],
"dial": res.value['dial'],
"order": res.value['order']
};
response.push(r);
res.continue();
}
}
cursor.oncomplete = function() {
callback(response);
}
} else {
// If both args are specified query specified index
store = store.index(ind);
var range = IDBKeyRange.bound(key, key);
store.openCursor(range).onsuccess = function(e) {
var res = e.target.result;
if(res) {
var r = {
"name": res.value['name'],
"url": res.value['url'],
"folder": res.value['folder'],
"colour": res.value['colour'],
"dial": res.value['dial'],
"order": res.value['order']
};
response.push(r);
res.continue();
}
}
cursor.oncomplete = function() {
callback(response);
}
}
};
答案 0 :(得分:2)
正如您在评论中指出的那样,您必须将依赖于数据库的操作放在从success
处理程序调用的函数中。
这种基于回调的编程很快就会变得很痛苦,一个常见的解决方案就是使用promises。
但是,使IndexedDB与promises一起使用仍在进行中(如果您有兴趣,请参阅https://github.com/inexorabletash/indexeddb-promises。)
如果您的目标是完成某项工作(而不是学习裸的IndexedDB API),或许您最好找一个wrapper library for IndexedDB(不能推荐一个,因为我和#39;我还没有尝试过与IDB认真合作。)
答案 1 :(得分:0)
我不建议使用像' db'这样的变量。就像你的例子中一样。如果您不熟悉读写异步Javascript,那么您只会给自己带来很多痛苦。有更好的方法来做到这一点。它需要几页来解释,并在StackOverflow上的许多其他问题中进行了解释,因此,非常简短地考虑重写代码以执行以下操作:
function createItem(db, ...) {
var tx = db.transaction(...);
// ...
}
function openIndexedDBThenCreateItem(...) {
var openRequest = indexedDB.open(...);
openRequest.onsuccess = function(event) {
var db = event.target.result;
createItem(db, ...);
};
}
function getItems(db, callback, ...) {
var tx = db.transaction(...);
var items = [];
tx.oncomplete = function(event) {
callback(items);
};
// ...
var request = store.openCursor(...);
request.onsuccess = function(event) {
var request = event.target;
var cursor = event.target.result;
if(cursor) {
var item = cursor.value;
items.push(item);
cursor.continue();
}
};
}
function openIndexedDBThenGetItems(db, callback, ...) {
var openRequest = indexedDB.open(...);
openRequest.onsuccess = function(event) {
var db = event.target.result;
getItems(db, callback, ...);
};
}
此外,您不需要等待DOMContentLoaded开始使用indexedDB。它立即可用。
如果你得到上面的代码,那么你可以考虑进一步改进添加一个简单的辅助函数:
function openIndexedDB(callback) {
var openRequest = indexedDB.open(...);
openRequest.onerror = callback;
openRequest.onsuccess = callback;
}
然后重写这样的例子:
function openIndexedDBThenCreateItem(...) {
openIndexedDB(function onOpen(event) {
if(event.type !== 'success') {
console.error(event);
} else {
var db = event.target.result;
createItem(db, ...);
}
});
}
function openIndexedDBThenGetItems(...) {
openIndexedDB(function onOpen(event) {
if(event.type !== 'success') {
console.error(event);
} else {
var db = event.target.result;
getItems(db, ...);
}
});
}