I found a lot of articles related to event cycle and task queue on the Internet, some of which are not very clear, and I still feel dizzy after reading them, so I write this blog to sort out the overall idea. If you have any different understanding or confusion, please leave a comment. This is my Github, welcome to visit.

Event loop and task queue are two important concepts in JS. These two concepts have different implementations in ES5 and ES6 standards. Especially in the ES6 standard, a clear distinction between macro and micro task queues explains some of Promise’s seemingly strange behavior.

Event loop

What is the event loop? Why is there an event loop? We all know that JS is single-threaded, but time-consuming operations like Ajax or DOM events need to be handled concurrently, otherwise a single thread will wait too long to do anything. Single-threaded loops are a form of concurrency, with only one event loop per thread. While task queues are used to complete operations in conjunction with the event loop, a thread can have multiple task queues.

Task queue

What is a task queue? So name think meaning, line up the task of the queue. A task is a notification returned by WebAPIs that tells the main JS thread that the asynchronous task has completed when it reads the task queue, and that the next step is to execute the callback function of the task. The main thread has multiple task queues, and different task queues are used to arrange tasks from different task sources. What is the source of the task? Such as setTimeout/Promise/DOM events are task sources. Tasks from similar task sources are said to be homologous. For example, setTimeout and setInterval are homologous. In ES6 standard, task queue is divided into macro task queue and micro task queue, which will be discussed in detail later.

Here is a general description of the event loop in ES5, as shown below (according to ruan yifeng’s tutorial) :

There are three big blocks in the picture:

  • Function call stack: execution stack.
  • WebAPIs: Browser interfaces. For example, aAjaxOperation, the main thread will send and receiveAjaxHanded to the browserAPIAnd then it goes on to do something else, and the browser is picking upAjaxAfter the data is returned, aAjaxCompleted events are placed behind the corresponding task queue.
  • Task queues: There are multiple task queues in the main thread. Same-origin tasks are placed in their own task queues.

A more specific chestnut. For example, a page opens with a

  1. The main thread is encounteringAjaxorsetTimeoutThis asynchronous operation will be handed to the browserWebAPIs, and continue to execute until the stack is empty.
  2. The browser will return the completed tasks at an unspecified time to the corresponding task queue.
  3. When the stack is empty, the main thread fetches tasks from the task queue, which tell you which callback functions to execute next. Task queues are prioritized, and the order of access is determined by priority. Priorities vary in different environments, so you can’t give a fixed priority.
  4. Each time a queue is accessed, the stack executes all the code in the task queue and fetches the code in the next task queue. If an asynchronous task currently belongs to the task queue is encountered during execution. The return of this task is not directly after the current task queue. Because these are two separate cycles of events, they will be separated.

This loop continues until all three blocks are empty, which is called an event loop.

Microtask queue

There are two types of task queues in ES6 standard. One is the microtask queue mentioned above, such as setTimeout, network request Ajax, user I\O, etc., and the other is macroTask Queue. Promises are part of the microtask queue. What happens to the event loop when you add microtask queues? In the process of execution stack, the tasks belonging to the micro task queue will be allocated to the corresponding micro task queue. After the call stack is empty, the main thread reads all the micro task queues first, then a macro task queue, and then all the micro task queues. As shown in figure:

Ok, a lot of conceptual stuff, not as clear as a piece of code:

setTimeout(function(){console.log(4)},0); new Promise(function(resolve){ console.log(1) for( var i=0 ; i<10000 ; i++ ){ i==9999 && resolve() } console.log(2)}).then(function(){ console.log(5)}); console.log(3);
  • Script starts execution, first encounteredsetTimeoutHand it to the browser for timingsetTimeoutAfter limiting the minimum timing, push the task insetTimeoutThe queue.
  • encounterPromiseConstructor, constructor arguments execute, output1, the callresolvechangePromiseObject state, and then output2.
  • PromiseThe objectthenMethod to push the task inPromiseTask queues.
  • performconsole.log(3)And the output3.
  • Call stack is empty, read the task queue, according to

    Read all microtask queues -> perform ->

    Read a macro task queue -> perform ->

    Read all microtask queues -> perform ->

    Read another macro task queue… The order.
  • Reads all tasks in the microtask queue and executes the callbacks specified by those tasks. performthenThe specified callback function outputs5Microtask queues also have priorities.
  • Finally readsetTimeoutExecute the callback function to output4.

So the final output order is 1,2,3,5,4, not 1,2,3,4,5. If the execution mechanism of the micro task queue is not clear, it is easy to lump two asynchronous tasks together and judge the execution order incorrectly.

Here is the event loop and task queue said more clear, refer to a lot of bosses blogs and discussion: www.ruanyifeng.com/blog/2014/1… www.zhihu.com/question/36… www.jianshu.com/p/12b9f73c5… www.cnblogs.com/hity-tt/p/6…

If you have different understanding, please leave a comment below the blog, this is my Github, welcome to visit, your star is my motivation.

  • Kongcheng.LC
  • Links to this article: Kongchenglc. Making. IO/blog/event loop 20…
  • Copyright Notice: All articles on this blog are licensed under a CC BY-NC-SA 3.0 license unless otherwise stated. Reprint please indicate the source!