如何在javascript中使用aynsc/await从异步操作返回对象
我一辈子都搞不懂async/await为什么会这样 考虑这个例子 我想要一个函数,它执行一些数据库初始化,并在完成时返回数据库对象如何在javascript中使用aynsc/await从异步操作返回对象,javascript,asynchronous,async-await,ecmascript-2017,Javascript,Asynchronous,Async Await,Ecmascript 2017,我一辈子都搞不懂async/await为什么会这样 考虑这个例子 我想要一个函数,它执行一些数据库初始化,并在完成时返回数据库对象 var globalDb = null; const IDB_DATABASE_NAME = "mydb"; const IDB_STORE_NAME = "mystore"; const IDB_VERSION = 1.0; async function initDb() { var idbOpenDbRequest = window.indexedD
var globalDb = null;
const IDB_DATABASE_NAME = "mydb";
const IDB_STORE_NAME = "mystore";
const IDB_VERSION = 1.0;
async function initDb() {
var idbOpenDbRequest = window.indexedDB.open(IDB_DATABASE_NAME, IDB_VERSION);
idbOpenDbRequest.onsuccess = function (event) {
return event.target.result;
};
}
(async () => {
globalDb = await initDb();
console.log("I should happen second")
console.log(globalDb);
})();
预期
顺便说一句,忘记这是关于indexedDb的,这个例子非常简单——我认为这与这个问题的主题无关 所以问题在于
initDb
函数。我将为您重新编写,然后解释此版本的工作原理:
function initDb() {
var idbOpenDbRequest = window.indexedDB.open(IDB_DATABASE_NAME, IDB_VERSION);
return new Promise((resolve, reject) => {
idbOpenDbRequest.onsuccess = function (event) {
setTimeout(function () {
console.log("I should happen first");
resolve(event.target.result);
}, 2000);
};
})
}
我所做的是将onsuccess
回调封装在承诺中。Javascript中的异步/等待模式基本上是基于承诺的。要么您自己返回一个承诺,要么它将结果包装成一个承诺(并立即解决它)
因为您自己没有返回承诺,所以它试图将返回值(未定义)封装在承诺中。然后,它立即解决了导致异步函数返回的问题
使用此更新的代码,调用initDb,然后返回一个承诺,该承诺只有在建立连接并触发超时后才能得到解决。对于异步/等待在这里的工作方式,确实存在一些混淆。我将尝试提供并回答,但同时可能会有所帮助?您正在等待
initDb()
,但您不能等待setTimeout
,因为它不会返回承诺,因此控制台会意外登录(实际上是预期的)订单和函数返回未定义,因为它没有返回任何内容。@因此他从setTimeout
回调返回内容,并希望它是initDb()
的返回@Kjensen它不是那样工作的。@VaibhavVishal我现在删除了setTimeout,它只是说明了一个关于计时的问题,这太愚蠢了,因为它增加了复杂性(在本例中,实际上把我的示例搞砸了)。基本问题/问题仍然是一样的:为什么函数没有返回任何内容?为什么console.log的顺序与我的预期不同?@Kjensen要从函数中获取某些内容,应该首先返回它。您是否从initDb
?)返回任何内容),实际上我正在编写相同的内容,但您的速度更快:O)删除async
,因为在函数中不使用wait关键字是错误的。我将删除async
关键字。@Kjensen您确实可以在使用和不使用async
的情况下使用该函数。我选择在答案中删除它,因为我没有在函数本身中使用await
关键字。@Mathyn,谢谢您提供的解释。这是有道理的