事件循环和Promise有什么关系 [英] What is the relationship between event loop and Promise

查看:23
本文介绍了事件循环和Promise有什么关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am curious about the relationship between Event Loop and Promise.
The demo exposes the question. I expected the p1 fulfilled appear in the middle, since they queue a task to the same task queue and are executed one by one.

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

的可视化效果示出了<代码>promise.then 的回调没有进入 Event Loop 的任务队列.对吗?

The visualized effect shows the promise.then's callback didn't go to the task queue of the Event Loop. It's right?

【注意:这个问题与 Promise vs setTimeout 不同,因为它更关注Event Loop和Promise的关系】

【NOTE: The question is not the same as Promise vs setTimeout, since it focus more on the relationship between Event Loop and Promise】

推荐答案

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

Each event loop has a microtask queue and a macrotask queue.

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

A microtask is a task that is originally to be queued on the microtask queue rather than a task queue. Refer to https://www.w3.org/TR/html51/webappapis.html#microtask-queue.

有两种微任务:

  • 单独回调微任务,例如Promise
  • 和复合微任务,例如 Node.js 中的 Object.observeMutationObserverprocess.nextTick.
  • solitary callback microtasks, such as Promise
  • and compound microtasks, such as Object.observe, MutationObserver and process.nextTick in Node.js.

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

And the macrotask queue mainly contains setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O in Nodejs.

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

In a event Loop, these two task queues will run in two steps:

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

在你的例子中:

  1. 首先,你的Promise初始化new Promiseresolve是同步的;
  2. 然后同步添加一个setTimeout宏任务到宏任务队列中;
  3. 然后将微任务promise.then(function(){})同步添加到微任务队列中,这个任务会立即运行,因为Promise的初始化和解析是同步的,这个任务在任何之前运行宏任务;所以,console.log p1 已完成;
  4. 然后将第二个宏任务setTimeout添加到宏任务队列中;
  5. 在这个事件循环结束后,运行两个宏任务;
  1. First, your Promise initialize new Promise and resolve are synchronous;
  2. and then synchronously add a setTimeout macroTask into the macrotask queue;
  3. then synchronously add the microtask promise.then(function(){}) to the microtask queue, this task will run immediately, because the Promise initialize and resolve are synchronous, this task run before any macrotask; so, console.log the p1 fulfilled;
  4. then add the second macrotask setTimeout to macrotask queue;
  5. after this event loop ended, run the two macrotasks;

对于此代码:

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. 继续运行其他宏任务;
  1. First add three macrotask setTimeout to macrotask queue, and a microtask promise.then() to the microtask queue;
  2. run a macrotask;
  3. If condition true run all microtasks, but it's false, so go to the next step;
  4. run the second macrotask;
  5. check whether the promise resolved or not, the condition is true, then run all microtasks;
  6. go on to run other macrotasks;

这篇关于事件循环和Promise有什么关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆