Javascript 使用indexedDB返回值';未定义';

Javascript 使用indexedDB返回值';未定义';,javascript,indexeddb,Javascript,Indexeddb,我正在尝试使用indexedDB 我的代码的某些部分是有效的 在下面的示例中,第一个函数在my DB中添加了服务器,但是在Chrome调试控制台中有一条与任何行无关的undefined消息。但服务器已添加 第二个函数将记录放入一个数组中,还有一条与任何行无关的undefined消息 如果我执行console.log(服务器)就在返回服务器之前我可以看到数组内容,但是如果我在代码的其他地方调用函数,返回的对象是未定义的 var dbName = 'myDBname', dbServersStore

我正在尝试使用indexedDB

我的代码的某些部分是有效的

在下面的示例中,第一个函数在my DB中添加了服务器,但是在Chrome调试控制台中有一条与任何行无关的
undefined
消息。但服务器已添加

第二个函数将记录放入一个数组中,还有一条与任何行无关的
undefined
消息

如果我执行
console.log(服务器)
就在
返回服务器之前
我可以看到数组内容,但是如果我在代码的其他地方调用函数,返回的对象是
未定义的

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;
    }
}
};

我不明白这个
未定义的
是从哪里来的,如果这就是
listServersInDB()
函数不起作用的原因。

您需要了解有关如何编写异步Javascript的更多信息。代码中的错误太多,甚至无法开始对问题进行推理

简而言之,不要这样做:

function open() {
  var openDatabaseRequest = ...;
}

openDatabaseRequest.foo = ...;
相反,请执行以下操作:

function open() {
  var openDatabaseRequest = ...;
  openDatabaseRequest.foo = ...;
}
接下来,您不需要多次尝试打开同一个数据库。你为什么叫indexedDB.open两次?您可以打开一个数据库来安装它并立即开始使用它。都使用相同的连接

接下来,我建议您不要将数据库打开请求命名为“myDB”。这是误导。这是一个IDBRequest对象,更具体地说,是一个IDBROpenRequest对象。请求不是数据库

接下来,您不能在最后从request.onsuccess返回服务器阵列。对于其中一个来说,这不会返回任何地方,并且可能是未定义的源。两次这将在每次游标前进时返回,因此多次返回服务器毫无意义。第三个原因是它返回得太早,因为在枚举所有服务器之前它无法返回。要正确返回,您需要等待,直到列出所有服务器。这意味着使用异步代码模式。例如,下面是使用回调的方法:

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);
}
当调用不返回值的函数时,它将返回未定义的值。JavaScript中的所有函数都返回未定义,除非显式返回其他函数

当您从devtools控制台调用一个函数,并且该函数返回undefined时,控制台将输出'->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()。如果您不在控制台中使用顶级wait,那么您将获得异步函数的典型返回值,这是一个Promise对象。要将承诺转换为其返回值,您必须等待它。

您需要了解有关如何编写异步Javascript的更多信息。代码中的错误太多,甚至无法开始对问题进行推理

简而言之,不要这样做:

function open() {
  var openDatabaseRequest = ...;
}

openDatabaseRequest.foo = ...;
相反,请执行以下操作:

function open() {
  var openDatabaseRequest = ...;
  openDatabaseRequest.foo = ...;
}
接下来,您不需要多次尝试打开同一个数据库。你为什么叫indexedDB.open两次?您可以打开一个数据库来安装它并立即开始使用它。都使用相同的连接

接下来,我建议您不要将数据库打开请求命名为“myDB”。这是误导。这是一个IDBRequest对象,更具体地说,是一个IDBROpenRequest对象。请求不是数据库

接下来,您不能在最后从request.onsuccess返回服务器阵列。对于其中一个来说,这不会返回任何地方,并且可能是未定义的源。两次这将在每次游标前进时返回,因此多次返回服务器毫无意义。第三个原因是它返回得太早,因为在枚举所有服务器之前它无法返回。要正确返回,您需要等待,直到列出所有服务器。这意味着使用异步代码模式。例如,下面是使用回调的方法:

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);
}
当调用不返回值的函数时,它将返回未定义的值。JavaScript中的所有函数都返回未定义,除非显式返回其他函数

当您从devtools控制台调用一个函数,并且该函数返回undefined时,控制台将输出'->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()。如果您不在控制台中使用顶级wait,那么您将获得异步函数的典型返回值,这是一个Promise对象。要将承诺转化为回报,你必须等待它。

清楚且有用的解释,谢谢

我多次打开数据库,因为第一次是为了检查数据库是否需要升级,并在需要时做一些事情。我将在每个函数中添加“db.close()”

然后,我尝试了你的例子,结果是一样的:
console.log('Loaded servers array from db:',servers)工作
但是
返回服务器不工作

控制台中已经有一个
未定义的
,没有相关行:


清楚且有用的解释,谢谢

我多次打开数据库,因为第一次是为了检查数据库是否需要升级,并在需要时做一些事情。我将在每个函数中添加“db.close()”

然后,我尝试了你的例子,结果是一样的:
console.log('Loaded servers array from db:',servers)工作
但是
返回服务器不工作

控制台中已经有一个
未定义的
,没有相关行: