首页 > 解决方案 > 对从异步函数返回的承诺感到非常困惑

问题描述

所以我知道 async 函数在遇到 await 关键字时会立即返回一个待处理的 promise,如果没有使用 await 关键字,则 async 函数返回的 promise 将被解析为我们从 async 函数返回的值,如下所示:

async function f() {
    let p = await (new Promise(r => {
        setTimeout(r, 2000, 100)
    }))
    return p;
}

let p = f();
console.log(p); // pending, because its awaiting.

第二个例子:

async function f() {
    let p = 'someValue';
    return p;
}
let p = f();
console.log(p); // {<fulfilled>: "someValue"}

第二个例子也很有意义,我们返回 'someValue',正如 MDN 所说,它包含在 Promise.resolve('someValue') 中,这就是返回的内容。

现在,这段代码打印的内容让我非常困惑,它记录了一个未决的承诺!

(我知道我没有在这里使用 await,这是故意的)

async function f() {
    let p = new Promise(r => r(113));
    return p;
}
let af = f();
console.log(af)

我们正在我们的 async f 函数中创建一个承诺,该承诺立即解决,这就是我在我的默认创建的异步函数承诺中返回的承诺,那么为什么该日志处于挂起状态?

即使它未决,当我展开该对象时,我也会同时看到:

[[PromiseResult]]: 113

有人可以帮忙吗?

标签: javascriptasynchronousasync-awaitpromise

解决方案


这可能是因为 JavaScript 引擎需要“扁平化”返回的 Promise。

console.log(Promise.resolve(113)); //=> fulfilled
const a = async () => 113;
console.log(a()); //=> fulfilled
const b = async () => Promise.resolve(113);
console.log(b()); //=> pending

最后一个场景记录了一个未决的承诺。这可能是因为 JavaScript 引擎看到您从异步函数返回了一个 Promise。在这种情况下,当您 时await b(),您期望113结果。异步函数总是返回一个 Promise。如果这个 Promise 的解析值(异步函数的返回值)是另一个 Promise,那么这个 Promise 就是“扁平化”的。

b为了更好地说明这一点,想象一下as(Firefox 控制台表示法)的返回值:

Promise { <state>: "pending", <value>: Promse { <state>: "fulfilled", <value>: 123 } }

而第一个代码块的返回值和a是:

Promse { <state>: "fulfilled", <value>: 123 }

嵌套 promise 的扁平化由引擎完成,并且可能添加到事件循环的末尾,因此在当前运行的上下文之后运行。这意味着外部承诺在发生之前一直处于未决状态。

这种行为可能取决于引擎,所以我不会依赖这种行为。实例是对最终价值的Promise承诺,应该这样对待。永远不要期望承诺会立即解决。如果你期望一个已经实现的承诺,你最好使用一个普通的同步函数,这样可以避免使用承诺。


推荐阅读