全局变量只能由第一个函数访问
Global variable only accessible to first function?
我对JS有一个不错的理解,但最终仍在学习。我正试图在IndexedDB上重新创建一个PHP/mySQL项目,但无法解释为什么我在这里看到错误。
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);
}
}
};
正如您在注释中所指出的,您必须将依赖于数据库的操作粘贴在从success
处理程序调用的函数中。
这种基于回调的编程很快就会成为一种痛苦,而常见的解决方案是使用promise。
然而,使IndexedDB与promise一起工作仍在进行中(请参阅https://github.com/inexorabletash/indexeddb-promises如果你感兴趣的话)。
如果你的目标是完成一些事情(而不是学习裸露的IndexedDBAPI),也许你最好为IndexedDB找到一个包装库(但我不推荐,因为我还没有认真尝试过使用IDB)。
我不建议像您在示例中那样使用"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, ...);
}
});
}
- javascript函数访问ios本机功能
- 从嵌套函数访问函数属性
- 将typescript函数访问到angular中
- 全局变量只能由第一个函数访问
- Javascript从匿名函数访问外部对象属性
- UI网格:如何从自定义函数访问MODEL_COL_FIELD
- 在jQuery中,我如何从$.ajax回调函数访问$(this)
- 如何在JavaScript中停止从特定函数访问某些函数和变量
- 从jQuery.ech()函数访问外部作用域
- Angular2/Typescript:从链接可观察函数访问实例变量
- 局部变量仍可通过函数访问
- 从Kendo中的columns.filterable.cell.template函数访问列字段名
- 可以't从JS函数访问combodate
- 如何在javascript中将变量从一个函数访问到另一个函数
- jQuery从PHP函数访问Ajax响应
- 如何从json函数访问javascript中的基类变量
- 在OPP JS中,您可以从构造函数访问原型函数内部声明的方法
- Javascript 使用函数访问其他类
- 从 JavaScript 中的私有函数访问公共函数
- 为什么我无法从茉莉花中的 javascript 函数访问全局变量