为什么在JavaScript中的await/async不如预期工作?

huangapple go评论64阅读模式
英文:

Why await/async in Javascript does not work as expected?

问题

作为学习JavaScript中的async/await的一种方式,我创建了以下JSFiddle示例代码:

async function func1() {
  return await setTimeout(() => {
  	console.log('执行 func1');
  }, 5000);
}

async function func2() {
  return await setTimeout(() => {
  	console.log('执行 func2');
  }, 2000);
}

async function mainFunc() {
	await func1();
  await func2();

  console.log('执行完成'); 
}

mainFunc();

由于我使用了await,我期望的输出将是:

执行 func1
执行 func2
执行完成

但令我惊讶的是,实际输出是:

执行完成
执行 func2
执行 func1

我一定漏掉了一些重要概念,欢迎任何建议。

英文:

As a way to learn async/await in Javascript, I created the following JSFiddle sample code

async function func1() {
  return await setTimeout(() => {
  	console.log('execute func1');
  }, 5000);
}

async function func2() {
  return await setTimeout(() => {
  	console.log('execute func2');
  }, 2000);
}

async function mainFunc() {
	await func1();
  await func2();

  console.log('execute completed'); 
}

mainFunc();

Since I have await, I expected the output will be:

execute func1
execute func2
execute complete

But to my surprise, the output is

execute complete
execute func2
execute func1

I must have missed some important concept on this, any suggestion is highly welcomed.

答案1

得分: 9

func1func2内部创建一个Promise

一旦你掌握了这个技巧,这就变得很容易,但如果你没有练习过,它可能一点都不明显。

setTimeout 本身不返回一个Promise:它返回一个可用于取消定时器的引用。

要得到一个Promise,你可以使用new Promise 构造函数。在简单的用法中,你需要传入resolve这个参数,以及你想要运行的函数,这里是setTimeout。在你的函数中,当你想要返回一个结果时,不要使用return,而是使用resolve

例如,如果你想要在延迟1秒后返回数字42,你可以使用以下方式。事实上,它立即返回一个Promise,1秒后解析为数字42。要实现在延迟后返回一个值的效果,你需要await结果。

return new Promise(resolve => {
  setTimeout(() => {
    resolve(42)
  }, 1000)
})

在你的情况下,你不需要从setTimeout中返回任何特定的结果,因此你不需要在resolve的括号内放任何内容。

实际上,resolve是一个虚拟的函数名,你可以使用任何变量名,但习惯上将其称为resolve以避免让读者感到困惑。

async function func1() {
  return new Promise(resolve => setTimeout(
    () => {
      console.log('执行 func1');
      resolve();
    }, 5000))
}

async function func2() {
  return new Promise(resolve => setTimeout(
    () => {
      console.log('执行 func2');
      resolve();
    }, 2000))
}

async function mainFunc() {
  await func1();
  await func2();
  console.log('执行完成');
}

mainFunc();

希望这有助于你理解如何在函数内创建Promise。

英文:

You have to create a promise inside func1 and func2

This is easy to do once you get the hang of it, but not at all obvious if you haven't practiced.

setTimeout itself does not return a promise: it returns a reference to the timer that can be used to cancel the timeout process.

To get a Promise instead, use the new Promise constructor. In simple use, you feed in the word resolve, and the function you want to run, in this case setTimeout. At the point in your function that you want to return a result, do not use return: instead use resolve.

For example, if you wanted to return the number 42 after a 1 second delay, you can use the following. It in fact immediately returns a promise that, after 1 second, resolves to the number 42. To get the effect of returning a value after a delay, you would need to await the result.

return new Promise(resolve, setTimeout(()=>{resolve(42)},1000)

In your case you don't want to return any particular result from the setTimeout, so you don't need to put anything inside the parentheses of resolve.

The word resolve is in fact a dummy function name: you could use any variable name but it is conventional to call it resolve to prevent unnecessary bafflement for readers.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

async function func1() {
  return new Promise(resolve =&gt; setTimeout(
    () =&gt; {
      console.log(&#39;execute func1&#39;);
      resolve()
    }, 5000))
}

async function func2() {
  return new Promise(resolve =&gt; setTimeout(
    () =&gt; {
      console.log(&#39;execute func2&#39;);
      resolve()
    }, 2000))
}

async function mainFunc() {
  await func1();
  await func2();
  console.log(&#39;execute completed&#39;);
}

mainFunc();

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年3月7日 13:50:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75658432.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定