如何在 javascript 中使用 aynsc/await 从异步操作返回对象

How to use aynsc/await in javascript for returning objects from asynchronous operations

我一辈子都弄不明白为什么 async/await 会这样。

考虑这个例子。

我想要一个执行一些数据库初始化的函数,returns 完成后将数据库对象交给我。

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

预计

  1. console.log("I should happen first")
  2. console.log("I should happen second")
  3. console.log(globalDb); //将对象转储到控制台

实际

  1. console.log("I should happen second")
  2. console.log(globalDb); //未定义
  3. console.log("I should happen first")

我意识到我从根本上误解了这里的某些东西。请赐教为什么 await 不能像我期望的那样工作。 :)

JsFiddle

https://jsfiddle.net/p2jqyrou/2/

Ps。忘记这是关于 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 回调包装在 Promise 中。 Javascript 中的 async/await 模式基本上基于 Promises。要么你自己return一个Promise,要么它把结果包装在一个Promise中(并立即解析它)。

因为您自己没有 return Promise,所以它试图将 return 值(未定义)包装在 Promise 中。然后它立即解决导致异步函数 return.

使用此更新后的代码 initDb 被调用,然后 return 是一个 Promise,它仅在建立连接并触发超时后才被解析。