使用 indexedDB returns 'undefined'
Use of indexedDB returns 'undefined'
我正在尝试使用 indexedDB。
我的部分代码有效。
在下面的示例中,第一个函数在我的数据库中添加了服务器,但是在 Chrome 调试控制台中有一条与任何行无关的 undefined
消息。虽然服务器已经添加。
第二个函数将记录放在一个数组中,还有一个 undefined
与任何行无关的消息。
如果我在 return servers;
之前执行 console.log(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()
功能不起作用的原因。
你需要进一步了解如何编写异步Javascript。您的代码中有太多错误甚至无法开始推理问题。
简单地说,不要这样做:
function open() {
var openDatabaseRequest = ...;
}
openDatabaseRequest.foo = ...;
相反,这样做:
function open() {
var openDatabaseRequest = ...;
openDatabaseRequest.foo = ...;
}
接下来,您无需多次尝试打开同一个数据库。为什么要调用 indexedDB.open 两次?您可以打开一个数据库来安装它并立即开始使用它。全部使用相同的连接。
接下来,我建议您不要将数据库打开请求命名为'myDB'。这是误导。这是一个 IDBRequest 对象,更具体地说,是一个 IDBOpenRequest 对象。请求不是数据库。
接下来,您不能 return 来自最后 request.onsuccess 的服务器数组。其中一个 returns 无处可去,可能是未定义的来源。每次游标前进时都会有两个 returns,因此多次 return return 服务器毫无意义。三是这个 return 太早了,因为它不能 return 直到所有服务器都被枚举。要正确 return 你需要等到所有服务器都列出来。这意味着使用异步代码模式。例如,这里是你如何使用回调来完成它:
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);
}
当您调用一个没有 return 值的函数时,它 return 是未定义的。 JavaScript return 中的所有函数均未定义,除非您明确 return 其他内容。
当您从 devtools 控制台调用一个函数,并且该函数 return 未定义时,控制台会打印出“-> undefined”。这是使用控制台的一个普通方面。
如果您想获得一个函数,return将服务器列表作为一个数组,那么,您不能。以假装的方式做到这一点的唯一方法是使用 'async' 函数和承诺。
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();
。如果您不在控制台中使用 top-level await,那么您将获得异步函数的典型 return 值,它是一个 Promise 对象。要将承诺转化为它的 return 值,您必须等待它。
清晰有用的解释,谢谢。
我多次打开数据库,因为第一次是为了检查数据库是否需要升级,并在需要时做一些事情。我将在每个函数中添加 'db.close()'。
然后,我试了你的例子,结果是一样的:
console.log('Loaded servers array from db:', servers);
有效
但是 return servers;
不起作用。
并且在控制台中已经有一个没有相关行的 undefined
:
Screenshot
我正在尝试使用 indexedDB。
我的部分代码有效。
在下面的示例中,第一个函数在我的数据库中添加了服务器,但是在 Chrome 调试控制台中有一条与任何行无关的 undefined
消息。虽然服务器已经添加。
第二个函数将记录放在一个数组中,还有一个 undefined
与任何行无关的消息。
如果我在 return servers;
之前执行 console.log(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()
功能不起作用的原因。
你需要进一步了解如何编写异步Javascript。您的代码中有太多错误甚至无法开始推理问题。
简单地说,不要这样做:
function open() {
var openDatabaseRequest = ...;
}
openDatabaseRequest.foo = ...;
相反,这样做:
function open() {
var openDatabaseRequest = ...;
openDatabaseRequest.foo = ...;
}
接下来,您无需多次尝试打开同一个数据库。为什么要调用 indexedDB.open 两次?您可以打开一个数据库来安装它并立即开始使用它。全部使用相同的连接。
接下来,我建议您不要将数据库打开请求命名为'myDB'。这是误导。这是一个 IDBRequest 对象,更具体地说,是一个 IDBOpenRequest 对象。请求不是数据库。
接下来,您不能 return 来自最后 request.onsuccess 的服务器数组。其中一个 returns 无处可去,可能是未定义的来源。每次游标前进时都会有两个 returns,因此多次 return return 服务器毫无意义。三是这个 return 太早了,因为它不能 return 直到所有服务器都被枚举。要正确 return 你需要等到所有服务器都列出来。这意味着使用异步代码模式。例如,这里是你如何使用回调来完成它:
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);
}
当您调用一个没有 return 值的函数时,它 return 是未定义的。 JavaScript return 中的所有函数均未定义,除非您明确 return 其他内容。
当您从 devtools 控制台调用一个函数,并且该函数 return 未定义时,控制台会打印出“-> undefined”。这是使用控制台的一个普通方面。
如果您想获得一个函数,return将服务器列表作为一个数组,那么,您不能。以假装的方式做到这一点的唯一方法是使用 'async' 函数和承诺。
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();
。如果您不在控制台中使用 top-level await,那么您将获得异步函数的典型 return 值,它是一个 Promise 对象。要将承诺转化为它的 return 值,您必须等待它。
清晰有用的解释,谢谢。
我多次打开数据库,因为第一次是为了检查数据库是否需要升级,并在需要时做一些事情。我将在每个函数中添加 'db.close()'。
然后,我试了你的例子,结果是一样的:
console.log('Loaded servers array from db:', servers);
有效
但是 return servers;
不起作用。
并且在控制台中已经有一个没有相关行的 undefined
:
Screenshot