事件循环和Promise之间有什么关系

Pag*_*eYe 12 javascript theory event-loop promise

我很好奇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)
Run Code Online (Sandbox Code Playgroud)

控制台结果是:

p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop
Run Code Online (Sandbox Code Playgroud)

可视化效果显示promise.then回调没有进入事件循环的任务队列.这是正确的?

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

Jia*_*ong 20

每个事件循环都有一个微任务队列和一个macrotask队列.

微任务是最初要在微任务队列而不是任务队列上排队的任务.请参阅https://www.w3.org/TR/html51/webappapis.html#microtask-queue.

有两种微任务:

  • 孤立的回调微任务,如Promise,
  • 和化合物microtasks,如Object.observe,MutationObserverprocess.nextTick在Node.js的

而宏任务队列主要包括setTimeout,setInterval,setImmediate,requestAnimationFrame,I/O在的NodeJS.

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

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

在你的例子中:

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

对于此代码:

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)
}
Run Code Online (Sandbox Code Playgroud)

输出顺序:

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
Run Code Online (Sandbox Code Playgroud)
  1. 首先将三个setTimeoutmacrotask添加promise.then()到macrotask队列,并将微任务添加到微任务队列;
  2. 运行一个macrotask;
  3. 如果条件为true则运行所有微任务,但它是假的,所以转到下一步;
  4. 运行第二个macrotask;
  5. 检查承诺是否已解决,条件为真,然后运行所有微任务;
  6. 继续运行其他macrotasks;