Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the relationship between event loop and Promise [duplicate]

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)

The console result is:

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 shows the promise.then's callback didn't go to the task queue of the Event Loop. It's right?

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

like image 420
PageYe Avatar asked Sep 23 '17 03:09

PageYe


People also ask

How does promise work in event loop?

The promise in the last section has fulfilled with a value, but you also want to be able to access the value. Promises have a method called then that will run after a promise reaches resolve in the code. then will return the promise's value as a parameter.

What is the event loop in JavaScript and what does it do?

JavaScript has a runtime model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks. This model is quite different from models in other languages like C and Java.

What is the precedence in event loop?

The event loop is actually composed of one or more event queues. In each queue, events are handled in a FIFO order. It's up to the browser to decide how many queues to have and what form of prioritisation to give them. There's no Javascript interface to individual event queues or to send events to a particular queue.

What is event and event loop?

That is where the event loop comes into picture, it takes the first event from the Event Queue and places it onto the stack i.e in this case the callback function. From here, this function executes calling other functions inside it, if any. This cycle is called the event loop and this how JavaScript manages its events.


1 Answers

Each event loop has a microtask queue and a macrotask 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.

There are two kinds of microtasks:

  • solitary callback microtasks, such as Promise
  • and compound microtasks, such as Object.observe, MutationObserver and process.nextTick in Node.js.

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. First, check whether there is a macrotask (call it X) in old macrotask queue ;
  2. If X exists and it is running, wait for it to go to the next step until it was complete; otherwise, goto the next step immediately;
  3. Second, run all microtasks of the microtask queue;
  4. and when run the microtasks, we can still add some more microtaks into the queue, these tasks will also run.

In your example:

  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;

for this code:

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) } 

the output order:

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. 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;
like image 182
JiangangXiong Avatar answered Sep 18 '22 14:09

JiangangXiong