【问题标题】:I am confused between JavaScript macro and micro tasks priority我对 JavaScript 宏任务和微任务优先级感到困惑
【发布时间】:2022-11-27 09:15:33
【问题描述】:

我正在阅读 JavaScript 堆栈中的微任务和宏任务。我写了这段代码:

Promise.resolve().then(function () {
      setTimeout(function () {
        console.log('from promise one');
      }, 0);
    }).then(() => {
      console.log('from promise two');
    });

    setTimeout(function () {
      console.log('from timeout');
    }, 0);

但我意识到 from timeout 在控制台中显示的速度比 from promise one 快......

据我了解,Promise. then() 是一个微任务并在宏任务之前执行,其中 from timeout 是这里的微任务......但是为什么先执行 timeout 然后执行 Promise. then

【问题讨论】:

    标签: javascript


    【解决方案1】:

    需要知道的重要事项:

    1. setTimeout 超时为0 将在下一个事件循环开始时运行该函数。
    2. Promise.resolve.then() 中的回调是微任务,将在事件循环的当前迭代中的所有宏任务完成后运行。

      这是一个完整的解释:

      // The promise.resolve() runs first.
      Promise.resolve()
          // Because the function calling the setTimeout is within a .then(), it will
          // be called at the END of the CURRENT iteration of the event look.
          .then(function () {
              // The callback inside this setTimeout will be run at the beginning of the
              // next event loop; however it will run after the "from timeout" log, because
              // the setTimeout is called AFTER the one at the very bottom of the file.
              setTimeout(function () {
                  console.log('from promise one');
              }, 0);
          })
          .then(() => {
              // This log will occur first. No other logs will happen on the beginning of the
              // first iteration of the event loop, because everything is being called as
              // macro tasks except for this one.
              console.log('from promise two');
          });
      
      // This setTimeout call runs before the other code above runs. That's because
      // it is being called as a macro task for the current iteration of the event
      // loop. The callback inside of it, however, will be called at the BEGINNING of
      // the NEXT event loop.
      setTimeout(function () {
          console.log('from timeout');
      }, 0);
      

      上面代码发生事情的顺序的快速概述:

      事件循环的第一次迭代:

      1. Promise.resolve()被称为
      2. 文件底部的setTimeout被调用。在循环的下一次迭代开始时记录“从超时开始”的队列。

        - 所有宏任务现已完成。转向微任务 -

        1. 首先调用 .then() 回调,其中的 setTimeout 将“from promise one”日志排队,以便在事件循环的下一次迭代开始时运行。
        2. 调用第二个.then()回调,并记录“from promise two”。

        事件循环的第二次迭代:

        1. “from timeout”首先被记录,因为它是在前一个事件循环迭代期间要排队的第一个宏任务。
        2. “来自承诺一”被记录。

          输出:

          from promise two
          from timeout
          from promise one
          

          查看 this short video 以获得事件循环、微任务和宏任务以及 JavaScript 中的异步编程的简洁解释。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-20
      • 1970-01-01
      • 2019-11-10
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多