【问题标题】:A weird thing with async functions in JavaScriptJavaScript 中的异步函数很奇怪
【发布时间】:2021-04-01 18:29:37
【问题描述】:
$ cat x.js
async function print() {
    console.log("abc");
}

print();
$ nodejs x.js
abc

怎么可能?! print() 返回一个未被等待的 Promise 对象,是吗?如果没有等待,那为什么console.log会被执行?

【问题讨论】:

  • 好吧,它应该打印你的console.log,因为你执行它,然后返回一个Promise对象,它应该有fulfilledundefined。这有什么奇怪的?
  • 这能回答你的问题吗? stackoverflow.com/questions/47227550/…
  • @choz 奇怪的是abc 确实被打印出来了。
  • @PraveenKumarPurushothaman 它没有。

标签: javascript node.js


【解决方案1】:

你可以说一个空函数本身返回undefined(实际上什么都不返回)。看看下面的示例;

function print() {}
var returnVal = print(); // undefined

您会注意到returnValundefined

现在,如果我们在test()body 中有一些东西,但你仍然没有传递任何返回值,那么returnVal 仍然是undefined

function print() {
    console.log('abc');
}
var returnVal = print(); // undefined

因此,为了使函数具有返回值,只需return 即可。

function print() {
    console.log('abc');
    return 1;
}
var returnVal = print(); // 1

当您将其转换为异步函数时。引用自MDN

  1. 异步函数的主体可以被认为是被零分割 或更多等待表达式。顶级代码,直至并包括 第一个等待表达式(如果有的话),同步运行。在 这样,没有等待表达式的异步函数将运行 同步。如果函数内部有等待表达式 正文,但是,异步函数将始终异步完成。

  2. 每个 await 表达式之后的代码可以被认为存在于 .then 回调。 这样一个promise链是渐进式的 通过函数的每个可重入步骤构造。回报 价值构成了链条中的最后一环。

现在,根据以上信息,以下是我们所知道的与您的问题相关的信息;

  1. 你的print() 没有返回任何东西,应该是undefined
  2. 异步函数将异步完成,这意味着它将始终返回Promise待处理已完成已拒绝

所以,在你的问题中说出来,这就是你的函数的实际作用;

async function print() {
    console.log("abc"); // Prints 'abc'
}

// Function above is equivalent to;

function printEquivalentInNonAsync() {
    console.log("abc"); // Prints 'abc'
}

var returnVal = print(); // `returnVal` is `undefined`

并且,回答你的问题

如果没有等待,那为什么执行console.log?

无论等待异步函数,它仍然执行! - Awaits just to ensure the line execution is halted until the Asynchronous function (Promise) has reached fulfilled or rejected。请注意,Promise 的第一个状态是pending

【讨论】:

  • 非等待异步函数何时执行?如果我有f() 而没有await,其中f 是同步函数中的异步函数怎么办?
  • 如果您使用 await 调用异步函数,它将返回解析值而不是承诺,在您的情况下为 undefined。如果你现在不使用await,那么它将返回Promise<undefined>
【解决方案2】:

是的,就像 choz 说的那样,异步函数会返回一个 Promise,即使您没有在代码中定义一个 Promise。

我认为在 await 语句中的所有承诺都得到解决后,这个返回的承诺就会实现。

我在下面的代码中对其进行了测试,它也返回了 Promise,它只有在所有 Promise 都解决后才会实现(在这种情况下是 3000 毫秒后):

async function print2() {
   await console.log("abc")
    await new Promise((res, rej) => {
        setTimeout(() => {res(33)},3000)
    })
    await new Promise((res, rej) => {
        setTimeout(() => {res(33)},50)
    })
}

【讨论】:

  • “在等待语句中的所有承诺都得到解决后,这个返回的承诺才得以实现” - 但是没有等待语句!
  • 对不起,我的陈述不清楚,我的意思是在异步函数中,返回的承诺在函数中的所有承诺都得到解决后得到解决(包括那些通过等待关键字声明的承诺,你知道await 3Promise.of(3)) 一样工作。虽然我不太清楚上述声明中返回的承诺与其他承诺之间的关系。
猜你喜欢
  • 1970-01-01
  • 2018-01-24
  • 2018-07-18
  • 1970-01-01
  • 2018-08-14
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多