代码之家  ›  专栏  ›  技术社区  ›  BlueDolphin

为什么Javascript中的wait/async不能按预期工作?

  •  4
  • BlueDolphin  · 技术社区  · 3 年前

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

    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();
    

    由于我一直在等待,我预计产出将是:

    execute func1
    execute func2
    execute complete
    

    但令我惊讶的是,输出是

    execute complete
    execute func2
    execute func1
    

    我一定错过了一些重要的概念,任何建议都是非常受欢迎的。

    1 回复  |  直到 3 年前
        1
  •  9
  •   Unmitigated    3 年前

    您必须在func1和func2内部创建promise

    一旦你掌握了窍门,这很容易做到,但如果你没有练习过,这一点就不明显了。

    setTimeout 它本身不返回promise:它返回一个对定时器的引用,该定时器可用于取消超时过程。

    要获得Promise,请使用 new Promise 构造函数。简单来说,你输入单词 resolve ,以及要运行的函数,在这种情况下 setTimeout 。在函数中要返回结果的点上,不要使用 return :改为使用 决定 .

    例如,如果您想返回数字 42 延迟1秒后,您可以使用以下内容。事实上 立即 返回一个promise,该promise在1秒后解析为数字 42 。要获得延迟后返回值的效果,您需要 await 结果。

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

    在您的情况下,您不想从setTimeout返回任何特定的结果,因此不需要在的括号内放入任何内容 决定 .

    单词 决定 实际上是一个伪函数名:您可以使用任何变量名,但调用它是常规的 决定 以防止读者感到不必要的困惑。

    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();