我正在尝试使用indexedDB。
我的代码的某些部分有效。
在以下示例中,第一个函数在我的数据库中添加服务器,但是在Chrome调试控制台中,有一条undefined
消息与任何行无关。已经添加了服务器。
第二个函数将记录放入数组中,还有一条undefined
消息与任何行无关。
如果我在console.log(servers);
之前做return servers;
我可以看到数组内容,但是如果我在我的代码中的其他地方调用该函数,则返回的对象为undefined
。
var dbName = 'myDBname',
dbServersStoreName = 'servers',
dbVersion = 1,
openDBforCreation = indexedDB.open(dbName, dbVersion);
openDBforCreation.onupgradeneeded = function(e) {
var db = e.target.result;
var objStore = db.createObjectStore(dbServersStoreName, { keyPath: "alias"
});
var index = objStore.createIndex("serversAlias", ["alias"]);
};
function addServerInDB(serverAlias,serverAddress,user,pwd){
var myDB = indexedDB.open(dbName, dbVersion);
myDB.onerror = function() {
var notification = document.querySelector('.mdl-js-snackbar');
notification.MaterialSnackbar.showSnackbar(
{message: 'Error while trying to access internal database'});
}
myDB.onsuccess = function(e) {
var db = e.target.result,
request = db.transaction([dbServersStoreName],
"readwrite").objectStore("servers")
.put({alias:''+serverAlias+'',
address:''+serverAddress+'', login:''+user+'',
passwd:''+pwd+''});
request.onsuccess = function(){
var notification = document.querySelector('.mdl-js-snackbar');
notification.MaterialSnackbar.showSnackbar(
{message: 'Server added'});
}
}
};
function listServersInDB(){
var myDB= indexedDB.open(dbName, dbVersion);
myDB.onerror = function() {
var notification = document.querySelector('.mdl-js-snackbar');
notification.MaterialSnackbar.showSnackbar(
{message: 'Error while trying to access internal database'});
}
myDB.onsuccess = function(e) {
var servers = new Array(),
db = e.target.result,
request = db.transaction(["servers"], "readwrite")
.objectStore("servers")
.openCursor();
request.onsuccess = function(e){
var cursor = e.target.result;
if(cursor){
servers.push(cursor.value);
cursor.continue();
}
return servers;
}
}
};
我不明白这个undefined
来自哪里,如果这就是listServersInDB()
函数不起作用的原因。
答案 0 :(得分:3)
您需要了解有关如何编写异步Javascript的更多信息。您的代码中有太多错误甚至无法开始推理问题。
简而言之,不要这样做:
function open() {
var openDatabaseRequest = ...;
}
openDatabaseRequest.foo = ...;
相反,这样做:
function open() {
var openDatabaseRequest = ...;
openDatabaseRequest.foo = ...;
}
接下来,您不需要多次尝试打开同一个数据库。你为什么两次调用indexedDB.open?您可以打开数据库以安装它并立即开始使用它。全部使用相同的连接。
接下来,我建议您不要将数据库打开请求命名为“myDB”。这是误导。这是一个IDBRequest对象,更具体地说,是一个IDBOpenRequest对象。请求不是数据库。
接下来,您无法从最终的request.onsuccess返回servers数组。对于一个这回到无处可能是未定义的来源。每次光标前进时都返回两次,因此多次返回返回服务器完全没有意义。三是这太早返回,因为它在枚举所有服务器之前无法返回。要正确返回,您需要等到列出所有服务器。这意味着使用异步代码模式。例如,以下是使用回调的方法:
function listServers(db, callbackFunction) {
var servers = [];
var tx = db.transaction(...);
var store = tx.objectStore(...);
var request = store.openCursor();
request.onsuccess = function() {
var cursor = request.result;
if(cursor) {
servers.push(cursor.value);
cursor.continue();
}
};
tx.oncomplete = function() {
callbackFunction(servers);
};
return 'Requested servers to be loaded ... eventually callback will happen';
}
function connectAndList() {
var request = indexedDB.open(...);
request.onsuccess = function() {
var db = request.result;
listServers(db, onServersListed);
};
}
function onServersListed(servers) {
console.log('Loaded servers array from db:', servers);
}
当您调用不返回值的函数时,它将返回undefined。除非您明确返回其他内容,否则JavaScript中的所有函数都将返回undefined。
当你从devtools控制台调用一个函数,并且该函数返回undefined时,控制台会输出' - >未定义”。这是使用控制台的一个普通方面。
如果你想获得一个将服务器列表作为数组返回的函数,那么你不能。以假装的方式做到这一点的唯一方法是使用“异步”功能和承诺。
async function getServers() {
var db = await new Promise(resolve => {
var request = indexedDB.open(...);
request.onsuccess = () => resolve(request.result);
});
var servers = await new Promise(resolve => {
var tx = db.transaction(...);
var request = tx.objectStore(...).getAll();
request.onsuccess = () => resolve(request.result);
});
return servers;
}
再一次编辑,如果要从控制台调用此功能,请使用await getServers();
。如果您不在控制台中使用顶级await,那么您将获得async函数的典型返回值,该函数是Promise对象。要将承诺变为其返回值,您必须等待它。
答案 1 :(得分:0)
明确且有帮助的解释,谢谢。
我多次打开数据库,因为第一次检查数据库是否需要升级并在需要时执行某些操作。我将在每个函数中添加'db.close()'。
然后,我尝试了你的例子,结果是一样的:
console.log('Loaded servers array from db:', servers);
有效
但是return servers;
不行。
在控制台中已经有一个没有相关行的undefined
: