如何在 javascript 中使用 aynsc/await 从异步操作返回对象
Posted
技术标签:
【中文标题】如何在 javascript 中使用 aynsc/await 从异步操作返回对象【英文标题】:How to use aynsc/await in javascript for returning objects from asynchronous operations 【发布时间】:2020-01-12 03:02:29 【问题描述】:我终其一生都无法弄清楚为什么 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.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);
)();
预期
-
console.log("我应该先发生")
console.log("我应该第二次发生")
console.log(globalDb); //将对象转储到控制台
实际
-
console.log("我应该第二次发生")
console.log(globalDb); //未定义
console.log("我应该先发生")
我意识到我从根本上误解了这里的一些东西。请告诉我为什么 await 不能像我预期的那样工作。 :)
JsFiddle
https://jsfiddle.net/p2jqyrou/2/
附言。忘记这是关于 indexedDb 的,并且这个示例非常简化 - 我认为这对于这个问题的主题并不重要。
【问题讨论】:
对于 async/await 在这里的工作方式确实有些混乱。我会尝试提供并回答,但与此同时,this 可能会有所帮助? 你正在等待initDb()
,但你不能等待setTimeout
,因为它没有返回承诺,因此控制台登录意外(实际上是预期的)命令和函数返回未定义没有返回任何东西。
@TheReason 他从setTimeout
回调返回东西,并期望它是initDb()
的返回。 @Kjensen 它不是那样工作的。
@VaibhavVishal 我现在删除了 setTimeout,它只是说明了关于时间的一点,这对我来说很愚蠢,因为它增加了复杂性(实际上在这种情况下搞砸了我的示例)。基本问题/问题仍然相同:为什么函数没有返回任何内容 - 为什么 console.log 的顺序与我的预期不同?
@Kjensen 为了从函数中获取一些东西,你应该先返回它。你有没有从initDb
返回任何东西?
【参考方案1】:
所以问题出在您的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
回调包装在Promise 中。 javascript 中的 async/await 模式基本上是基于 Promises 的。要么您自己返回 Promise,要么将结果包装在 Promise 中(并立即解决它)。
因为您自己没有返回 Promise,所以它试图将返回值(未定义)包装在 Promise 中。然后它立即解决了导致异步函数返回的问题。
使用此更新后的代码initDb
被调用,然后返回一个 Promise,该 Promise 仅在建立连接并触发超时后才解决。
【讨论】:
)),实际上我在写同样的东西,但你更快:O) 删除async
,因为它会误导
最好不要在函数中使用 await 关键字。我将删除 async
关键字。
@Kjensen 您确实可以在有和没有async
的情况下使用该功能。我选择在答案中删除它,因为我没有在函数本身中使用 await
关键字。
@Mathyn 也感谢您提供解释。这说得通。 :)以上是关于如何在 javascript 中使用 aynsc/await 从异步操作返回对象的主要内容,如果未能解决你的问题,请参考以下文章
如何在 jQuery 选择器中使用 JavaScript 变量?
在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在