英文:
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
在func1
和func2
内部创建一个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 => setTimeout(
() => {
console.log('execute func1');
resolve()
}, 5000))
}
async function func2() {
return new Promise(resolve => setTimeout(
() => {
console.log('execute func2');
resolve()
}, 2000))
}
async function mainFunc() {
await func1();
await func2();
console.log('execute completed');
}
mainFunc();
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论