如何在 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 从异步操作返回对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中使用可枚举

如何在javascript中使用表达式查找'/'字符

如何在 JavaScript 中使用 DCMTK 库

如何在 Javascript 中使用路由

如何在 jQuery 选择器中使用 JavaScript 变量?

在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在