javascript - 事件循环和Promise有什么关系

标签 javascript promise theory event-loop

<分区>

很好奇Event Loop和Promise的关系
该演示暴露了这个问题。我希望 p1 fulfilled 出现在中间,因为它们将任务排队到同一个任务队列并一个接一个地执行。

var p1 = new Promise(function(resolve, reject){
    resolve(1)
})
setTimeout(function(){
  console.log("will be executed at the top of the next Event Loop")
},0)
p1.then(function(value){
  console.log("p1 fulfilled")
})
setTimeout(function(){
  console.log("will be executed at the bottom of the next Event Loop")
},0)

控制台结果是:

p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop

The visualized effect显示 promise.then 的回调没有进入事件循环的任务队列。是吗?

【注意:问题与Promise vs setTimeout不一样】 ,因为它更关注Event Loop和Promise之间的关系】

最佳答案

每个事件循环都有一个微任务队列和一个宏任务队列。

microtask 是本来要在microtask 队列而不是task 队列中排队的任务。引用https://www.w3.org/TR/html51/webappapis.html#microtask-queue .

有两种微任务:

  • 单独的回调微任务,例如Promise
  • 和复合微任务,例如 Node.js 中的 Object.observeMutationObserverprocess.nextTick

而宏任务队列主要包含setTimeoutsetIntervalsetImmediaterequestAnimationFrameI/O 在 Nodejs 中。

在一个事件循环中,这两个任务队列会分两步运行:

  1. 首先检查旧的宏任务队列中是否有宏任务(称之为X);
  2. 如果X存在并且正在运行,等待它进入下一步,直到它完成;否则,立即进入下一步;
  3. 其次,运行微任务队列的所有微任务;
  4. 并且在运行微任务时,我们仍然可以在队列中添加更多的微任务,这些任务也会运行。

在你的例子中:

  1. 首先,你的Promise初始化new Promiseresolve是同步的;
  2. 然后在宏任务队列中同步加入一个setTimeout宏任务;
  3. 然后同步添加微任务promise.then(function(){})到微任务队列,这个任务会立即运行,因为Promise初始化和解析是同步的,这个任务先于任何宏任务;所以,console.log p1 fulfilled;
  4. 然后将第二个宏任务setTimeout添加到宏任务队列中;
  5. 在此事件循环结束后,运行两个宏任务;

对于这段代码:

setTimeout(function() {
  console.log("will be executed at the top of the next Event Loop")
}, 0)
var p1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve(1)
  }, 0)
});
setTimeout(function() {
  console.log("will be executed at the bottom of the next Event Loop")
}, 0)
for (var i = 0; i < 100; i++) {
  (function(j) {
    p1.then(function(value) {
      console.log("promise then - " + j)
    });
  })(i)
}

输出顺序:

will be executed at the top of the next Event Loop
promise then - 0
promise then - 1
promise then - 2
...
promise then - 99
will be executed at the bottom of the next Event Loop
  1. 首先在宏任务队列中加入三个宏任务setTimeout,在微任务队列中加入一个微任务promise.then()
  2. 运行宏任务;
  3. 如果条件为真,则运行所有微任务,但为假,则进行下一步;
  4. 运行第二个宏任务;
  5. 检查promise是否解决,条件为真,然后运行所有微任务;
  6. 继续运行其他宏任务;

关于javascript - 事件循环和Promise有什么关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46375711/

相关文章:

javascript - 如何将此函数转换为不使用 Promise 构造函数反模式

javascript - JavaScript 中的单子(monad)?

javascript - 等待递归 readdir 函数结束

javascript - 如何将速度参数分配给回调函数

javascript - 我已经为元素的宽度设置了动画,但是当动画开始时元素的边框消失了

javascript - 使用 javascript 检查 obj 中的属性

javascript - 如何在for循环中组织promise并在javascript中的函数之间传递参数?

mysql - 数据CRUD操作的理论基础

multithreading - 分布式计算与线程

javascript - 将 SQL 数组数据解析为 php mail()