简体   繁体   English

JS 中的异步/等待混淆

[英]Async/Await confusion in JS

I was learning asynchrony in JS and came across Async/Await.我在 JS 中学习异步并遇到了 Async/Await。 Then, I came across this code:然后,我遇到了这段代码:

function scaryClown() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('🤡');
    }, 2000);
  });
}

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

msg(); // Message: 🤡 <-- after 2 seconds

Thus, I have questions on the above code.因此,我对上面的代码有疑问。 Firstly, how can async function msg() return message value if the function itself returns only undefined Promise, that is, the function does not explicitly use return keyword.首先,如果函数本身只返回未定义的 Promise,即函数没有明确使用 return 关键字,那么异步函数 msg() 如何返回消息值。 Secondly, does await returns Promise or value itself having been unwrapped from Promise?其次,await 是否返回 Promise 或 value 本身已经从 Promise 解包?

function scaryClown() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('🤡');
    }, 2000);
  });
}

The above function is a function which returns a promise when it is called, but will only be resolved after 2 seconds.上面的函数是一个在调用时返回一个promise的函数,但只会在2秒后被解析。

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

the above function is asynchronous function which awaits for the promise to be resolved (in your case, after 2 seconds) and then only the console.log() triggers.上面的函数是异步函数,它等待承诺得到解决(在你的情况下,2 秒后),然后只有 console.log() 触发。

Note : any lines of code below the function msg() gets executed irrespective of the promise and the asynchronous function.注意:函数 msg() 下的任何代码行都会被执行,而不管 promise 和异步函数如何。

Running code snippet运行代码片段

 function scaryClown() { return new Promise(resolve => { setTimeout(() => { resolve('🤡'); }, 2000); }); } async function msg() { console.log(scaryClown()); // try without await, so it will not wait for the result and prints first, but an unresolved promise const msg = await scaryClown(); // actual result which is resolved, because we awaited console.log('Message:', msg); // Prints once the resolved value is available. } msg(); //executes first but only prints the value once it is resolved. console.log('I will continue executing irrespective of async func msg()');

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

await resolves promise and return resolved value. await 解析 promise 并返回解析值。 so above code with then can be written like below.所以上面的代码可以像下面这样写。 hope this makes you understand async await.希望这能让你理解异步等待。

function msg() {
  scaryClown().then(msg => {
    console.log('Message:', msg);
  });    
}

This is what happens:这是发生的事情:

When the async function (ie msg ) is invoked, it creates a promise object (let's call it P), which it will return when it deals with an await expression.async函数(即msg )被调用时,它会创建一个 promise 对象(我们称之为 P),它会在处理await表达式时返回。 scaryClown() executes, which sets the timer and returns yet another promise object; scaryClown()执行,它设置计时器并返回另一个承诺对象; let's call it Q. Then await is processed: at that moment the function returns the promise P. This promise is not resolved at that moment;让我们称它为 Q。然后await被处理:在那个时刻函数返回承诺 P。这个承诺在那一刻没有被解决; it is pending.它正在等待中。

If then there is any other code that followed the call of msg() , then that is executed like would be the case after any function call.如果在msg()调用之后还有任何其他代码,那么它的执行就像在任何函数调用之后的情况一样。 Execution continues until the call stack is empty.继续执行直到调用堆栈为空。

Then, some time later the timer event that was scheduled by scaryClown() will fire, and the corresponding promise Q resolves.然后,一段时间后,由scaryClown()安排的计时器事件将触发,相应的承诺 Q 将解析。 Because this promise Q was in an await expression, this resolution triggers a restoration of the execution context of msg() , where the await expression is now evaluated to be Q's resolved value, ie "🤡".因为这个promise Q 在await表达式中,这个解析触发了msg()的执行上下文的恢复,其中await表达式现在被评估为Q 的解析值,即“🤡”。

The variable msg gets this value assigned, and it is displayed with console.log .变量msg获得分配的这个值,并与console.log显示。 Then the function completes, in this particular case without any explicit return .然后函数完成,在这种特殊情况下没有任何显式return Remember that the function had already returned , so this is not really a normal return: code execution really ends here, as there is nothing on the call stack.请记住,该函数已经返回了,所以这不是一个真正的正常返回:代码执行真正到此结束,因为调用堆栈上没有任何内容。 This makes the promise P resolve.这使得承诺 P 解决。 If there had been an explicit return statement, with a value, the promise P would have been resolved with that value.如果有一个显式的return语句,带有一个值,promise P 就会用那个值解析。 But since there is no such return statement in your example, promise P resolves with undefined .但是由于您的示例中没有这样的return语句,promise P 用undefined解析。

As you don't do anything with the value returned by msg() , you don't really see what it returns.由于您没有对msg()返回的值执行任何操作,因此您实际上看不到它返回的内容。 If you would have done:如果你会这样做:

msg().then(console.log);

... you would have seen undefined in the console. ...您会在控制台中看到undefined

Your questions:你的问题:

how can async function msg() return message value if the function itself returns only undefined Promise, that is, the function does not explicitly use return keyword.如果函数本身只返回未定义的 Promise,即函数没有明确使用return关键字,那么async function msg()如何返回消息值。

The msg() call does currently not provide you with the message value. msg()调用当前为您提供消息值。 Instead it uses console.log to output it, but that is not the value returned by msg() .相反,它使用console.log输出它,但这不是msg()返回的值。 The returned value is a promise.返回的值是一个承诺。 Even if it had an explicit return keyword, it would still not make msg() return something else than a promise.即使它有一个明确的return关键字,它仍然不会让msg()返回一个承诺以外的东西。 The only difference would be what value that promise would eventually resolve to.唯一的区别是承诺最终会解析为什么

does await returns Promise or value itself having been unwrapped from Promise? await返回 Promise 或 value 本身已经从 Promise 解包?

await does two things at two different moments in time. await在两个不同的时刻做两件事。 First it makes the function return to the caller.首先它使函数返回给调用者。 Then, when the promise that it awaits resolves, it makes the function continue to run again, and await represents at that moment the promised value , which can therefore be assigned to a variable (or used in another way).然后,当它等待的承诺解决时,它使函数再次继续运行,并且await代表当时承诺的,因此可以将其分配给变量(或以其他方式使用)。

I personally don't use the verb "unwrapped" when talking about promises.我个人在谈论承诺时不使用动词“解开”。 But yes, the expression await promise evaluates (asynchronously) to the value that promise fulfils to.但是是的,表达式await promise计算(异步)到promise实现的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM