使用Async/Await在多个SetTimeout上

3
为了理解async/await,我尝试在settimeout运行和过期后显示控制台消息。如何修复下面的代码?我有5个settimeout函数,每个函数在完成后应该显示相应的消息。

function t1(){
    setTimeout(() => {
    console.log("1")
    }, 1000);
}

function t2(){
    setTimeout(() => {
    console.log("2")
    }, 2000);
}

function t3(){
    setTimeout(() => {
    console.log("3")
    }, 3000);
}

function t4(){
    setTimeout(() => {
    console.log("4")
    }, 4000);
}

function t5(){
    setTimeout(() => {
    console.log("5")
    }, 5000);
}

async function main(){
    await t1();
    console.log("1sec done");
    await t2();
    console.log("2sec done");
    await t3();
    console.log("3sec done");
    await t4();
    console.log("4sec done");
    await t5();
    console.log("Yay! I am all done");
}
main();


async-await 是用于处理 Promise 的。 - AZ_
3个回答

4

你应该使用Promise

function t1(){
    return new Promise(function(resolve, reject) {
      setTimeout(() => {
        console.log("1");
        resolve();
      }, 1000);
   });
}

function t2(){
    return new Promise(function(resolve, reject) {
      setTimeout(() => {
        console.log("2");
        resolve();
      }, 1000);
   });
}

function t3(){
    return new Promise(function(resolve, reject) {
      setTimeout(() => {
        console.log("3");
        resolve();
      }, 1000);
   });
}

function t4(){
    return new Promise(function(resolve, reject) {
      setTimeout(() => {
        console.log("4");
        resolve();
      }, 1000);
   });
}

function t5(){
    return new Promise(function(resolve, reject) {
      setTimeout(() => {
        console.log("5");
        resolve();
      }, 1000);
   });
}

async function main(){
    await t1();
    console.log("1sec done");
    await t2();
    console.log("2sec done");
    await t3();
    console.log("3sec done");
    await t4();
    console.log("4sec done");
    await t5();
    console.log("Yay! I am all done");
}
main();


2
你犯了两个错误:
  • 首先,在调用函数 t1,t2,t3... 之前,你使用了 await。应该在Promise上使用 await
  • 你正在将 1000,2000,... 传递给 setTimeout()。你应该创建一个返回在1秒后解析的Promise的函数
  • 在该函数返回的 Promise 前使用 await
"Original Answer" 翻译成 "最初的回答"

let afterOne = (num) => new Promise(res => {
    setTimeout(()=>{
      //log the number passed to function after 1000 ms
      console.log(num);
      //resolve the current promise so then next setTimeout could be set
      res();
   },1000)
  })
async function main(){
    /*This loop does same as
       await afterOne(0);
       await afterOne(1);
       await afterOne(2)
       await afterOne(3);
       await afterOne(4);
    */
    for(let i = 0;i<5;i++){
      await afterOne(i)
    }
}
main();


1
对于每个函数t1()t5(),您需要确保它们返回一个Promise,以便在内部的setTimeout()计时器完成后,返回的promise被“resolved”。
通过以这种方式返回Promise对象,您的t1()t5()函数实际上成为async方法,这意味着await前缀将导致执行main()阻塞,直到每个t1()t5()函数完成(或“resolved”)。
为了说明这一点,请考虑以下代码,其中一个通用的delay()函数替换了原始代码中的t1()t5()函数:

/* I've defined a generic delay function as replacement
for t1 - t5 functions to minimise the amount of code */
function delay(seconds) {

  /* Return a promise object that will cause the
  await to prevent main() async function's execution
  from continuing until this promise has resolved */
  return (new Promise((resolve) => {

    /* Inside the promise, set your time out */
    setTimeout(() => {
      console.log(seconds)

      /* When time out complete, call resolve(), which
      resolves this promise and allows main() async 
      function's execution to continue */
      resolve()
    }, seconds * 1000);

  }))

}

async function main() {
  await delay(1);
  console.log("1sec done");
  await delay(2);
  console.log("2sec done");
  await delay(3);
  console.log("3sec done");
  await delay(4);
  console.log("4sec done");
  await delay(5);
  console.log("Yay! I am all done");
}
main();


我已经了解到在函数前加上 async 会使其返回 Promise。因此,如果我像这样声明 t1-t5 函数 async function t1(){...},是否会有任何区别,因为它们也会返回 Promises? - vegabond
在你的函数声明前放置async关键字不会自动使该函数按照你所期望的方式运行。这样做基本上意味着,你可以在调用t1()函数内的其他异步函数时使用await关键字——希望这有所帮助。 - Dacre Denny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接