我在理解async/await
的整个概念时遇到了麻烦,并且花了很多时间阅读文档并尝试使用示例。但是我仍然不明白为什么这个小例子不起作用。
我想要的结果是让document.body.innerHTML
包含文本“ 123”,因为doFirst()
应该在doSomething()
完成之前完成运行。
但是我总是得到“ 132”,好像我根本没有使用异步/等待。我在做什么错了?
async function doFirst() {
document.body.innerHTML = document.body.innerHTML + "1";
setTimeout(function() {
document.body.innerHTML = document.body.innerHTML + "2";
}, 500);
}
async function doSomething()
{
await doFirst();
document.body.innerHTML = document.body.innerHTML + "3";
}
doSomething();
很抱歉再次发布此帖子,上次我发布此问题时被标记为重复。因此,这一次我想澄清的是,我没有在寻找任何能告诉我如何正确执行操作的答案,而且还没有解释为什么为什么我的代码无法正常工作。
答案 0 :(得分:4)
这是因为doFirst()
返回了一个承诺,该承诺在计时器用尽之前已解决。与您的期望相反,setTimeout
不会暂停脚本执行。
为了确保doFirst()
在计时器用完后解析 ,您需要将整个函数包装在Promise
对象中。计时器一旦用尽,就会调用resolve()
方法,例如:
function doFirst() {
return new Promise(resolve => {
document.body.innerHTML = document.body.innerHTML + "1";
setTimeout(function() {
document.body.innerHTML = document.body.innerHTML + "2";
resolve();
}, 500);
});
}
async function doSomething()
{
await doFirst();
document.body.innerHTML = document.body.innerHTML + "3";
}
doSomething();
如果您想避免使用callback hell,一种更干净的方法是简单地创建一个实用函数,该函数在setTimeout之后解析诺言,那么您可以等待从该函数返回的诺言进行打印,然后再打印“ 2 ”进入DOM:
// Utility function that resovles a promise after a given duration
function sleep(duration) {
return new Promise(resolve => setTimeout(resolve, duration));
}
async function doFirst() {
document.body.innerHTML = document.body.innerHTML + "1";
await sleep(500);
document.body.innerHTML = document.body.innerHTML + "2";
}
async function doSomething()
{
await doFirst();
document.body.innerHTML = document.body.innerHTML + "3";
}
doSomething();
答案 1 :(得分:2)
看看下面的代码:
npm install "@material-ui/lab"
您在做什么错?
您没有在yarn add "@material-ui/lab"
中返回承诺,因此该操作不是异步的(简而言之,您的代码
async function doFirst() {
document.body.innerHTML = document.body.innerHTML + "1";
return myAsyncFunc(500)
}
function myAsyncFunc(delay) {
return new Promise(resolve => setTimeout(function() {
document.body.innerHTML = document.body.innerHTML + "2"
resolve();
}, delay));
}
async function doSomething()
{
await doFirst();
document.body.innerHTML = document.body.innerHTML + "3";
}
不会等待doFirst()
完成并移至第{行) {1}})
注意:
如何立即运行doSomething()
并返回doFirst()
(基本上返回document.body.innerHTML = document.body.innerHTML + "3";
)。
500毫秒后,document.body.innerHTML = document.body.innerHTML + "1";
执行并运行myAsyncFunc
。之后,返回下一行Promise
,这标志着setTimeout
要完成。
document.body.innerHTML = document.body.innerHTML + "2"
一旦返回return resolve()
就结束了,因此添加了“ 3”
答案 2 :(得分:0)
我认为您可能对async
关键字的功能有误解。尽管它具有名称,它并不能神奇地将函数更改为异步。它仅做以下两件事:
await
在函数体内使用。但是只有当这两个一起使用时,它才真正有用。主体中没有await
的异步函数根本不需要是异步的。
您的示例函数doFirst
不使用await
,因此它基本上等同于以下内容:
function doFirst() {
document.body.innerHTML = document.body.innerHTML + "1";
setTimeout(function() {
document.body.innerHTML = document.body.innerHTML + "2";
}, 500);
return Promise.resolve(undefined);
}
如您所见,此代码没有异步的地方。 Promise.resolve
返回一个可以立即解析为给定值的承诺。这意味着在await doFirst()
中使用doSomething
实际上不会等待任何事情,因为承诺已经解决。
您希望doFirst
执行的操作是返回一个承诺,该承诺在执行setTimeout
回调之前将无法解决。不幸的是,setTimeout
没有返回承诺,因此您需要手动创建一个承诺:
function doFirst() {
document.body.innerHTML = document.body.innerHTML + "1";
return new Promise(function(resolve, reject) {
setTimeout(function() {
document.body.innerHTML = document.body.innerHTML + "2";
resolve();
}, 500);
});
}
您可能会注意到这里不需要async
关键字。这是因为该函数未使用await
,而已经返回了一个Promise。 doSomething
仍然可以使用await doFirst()
,因为await
可以与任何promise一起使用,而不仅是在调用异步函数时。