javascript - 对从异步函数返回的承诺感到非常困惑
问题描述
所以我知道 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
有人可以帮忙吗?
解决方案
这可能是因为 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
承诺,应该这样对待。永远不要期望承诺会立即解决。如果你期望一个已经实现的承诺,你最好使用一个普通的同步函数,这样可以避免使用承诺。
推荐阅读
- jestjs - 无法期望具有不同参数的`toHaveBeenNthCalledWith`
- qubole - 在 testdrive 帐户中休息 api?
- javascript - 如何通过 React 中的对象数组 .map()
- javascript - 无法在反应引导模式中使用我的可重用反应组件
- regex - 熊猫替换不适用于正则表达式 \([AZ]+\:[AZ]+\)
- reactjs - 输入值清除 - React Hooks
- jenkins - 如何使用自定义提交消息设置 web-hook?
- r - 包括出现值的所有行,否则,删除
- java - 如何使用 maven 构建 Javafx + Spring 进行生产
- mysql - 具有多个 AND OR 条件的原则