This is the 17th day of my participation in the August Text Challenge.More challenges in August

The first contact with JS micro task and macro task is in an interview, completely ignorant force, the following thrown out to test, we sneak peek:

console.log('script start');
new Promise(function(resolve){
    console.log('promise then');
console.log('script end');
Copy the code

In order to figure out what is going on in the end, looking for a long time did not find the right answer, now put my query results sorted out as follows, below we fundamentally explain JS micro task and macro task

JS execution mechanism

Javascript is a single-threaded language. Web-worker was proposed in the latest HTML5, but the core that javascript is single-threaded remains unchanged. So all javascript versions of “multithreading” are modeled with a single thread.

Multithreading: Programs can do several things at the same time. Single-threaded: a program can only do one thing at a time.

1. Why is JS single threaded?

One of the hallmarks of the JavaScript language is single-threaded, which means you can only do one thing at a time. So why can’t JavaScript have multiple threads? It’s more efficient.

The single thread of JavaScript, relative to its purpose. As a browser scripting language, JavaScript’s primary purpose is to interact with users and manipulate the DOM. This means that it has to be single-threaded, which can cause complex synchronization problems. For example, if there are two threads of JavaScript at the same time, one thread adds content to a DOM node, and the other thread removes that node, which thread should the browser use? So, to avoid complexity, JavaScript has been single-threaded since its inception, and this has been a core feature of the language and will not change.

In order to make use of the computing power of multi-core CPU, HTML5 proposes the Web Worker standard, which allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and cannot operate DOM. So, this new standard doesn’t change the single-threaded nature of JavaScript.

2. Why is JS asynchronous?

If asynchrony is not present in JS, it can only be executed from top to bottom, and if the previous line takes too long to parse, the following code will be blocked. For users, blocking means “stuck”, which leads to a poor user experience.

3, how is the JS single thread asynchronous?

Since JS is single-threaded, can only be executed on a thread, how to achieve asynchronous? Is through the event loop (Event loop), understand the event loop mechanism, understand the JS execution mechanism. Before we understand the event loop mechanism, let’s look at the task queue.

Task queue

A “task queue” is a queue of events (also known as a message queue). When an IO device completes a task, it adds an event to the “task queue”, indicating that the related asynchronous task can be placed on the “execution stack”. The main thread reads the “task queue”, which is to read what events are in it. In addition to the IO device events, the “task queue” includes some user-generated events (such as mouse clicks, page scrolling, and so on). As long as the callback function is specified, these events are queued up for the main thread to read.

A “task queue” is a first-in, first-out data structure in which the first events are read by the main thread first. The reading of the main thread is basically automatic. As soon as the stack is emptied, the first event in the “task queue” is automatically sent to the main thread. However, due to the “timer” function mentioned later, the main thread first checks the execution time, and certain events cannot be returned to the main thread until the specified time.

After reading an asynchronous task, the first step is to put the asynchronous task into the Event Table. When the asynchronous task in the Event table completes something or achieves certain conditions (such as setTimeout Event, mouse click, data file acquisition), These asynchronous tasks are pushed to the Event Queue, and the asynchronous tasks are only read when the stack is idle.

4. Javascript execution mechanism

The main thread reads events from the “task queue” in a continuous Loop, so the whole operation mechanism is also called an Event Loop. Event Loop is the javascript execution mechanism

Synchronous tasks and asynchronous tasks

1. Single thread deficiency

Single threading means that all tasks need to queue until the first task is finished and the next task can be executed. If the first task takes a long time, the second task has to wait forever. If the queue is due to a large amount of computation and the CPU is too busy, it is fine, but many times the CPU is idle because the IO devices (input and output devices) are slow (such as Ajax operations reading data from the network) and have to wait for the results to come out before executing.

2. Synchronous and asynchronous solutions to the single thread deficiency

The designers of the JavaScript language realized that the main thread could simply ignore the IO device, suspend the pending task and run the next one first. Wait until the IO device returns the result, then go back and continue the pending task.

Thus, all tasks can be divided into two types, synchronous and asynchronous.

Synchronous and asynchronous tasks go to different execution “places”, synchronous tasks go to the main thread, asynchronous tasks go to the Event Table and register functions. When the specified Event completes, the Event Table moves this function to the Event Queue. If the tasks in the main thread are empty after execution, the Event Queue will read the corresponding function and enter the main thread for execution. This process is repeated over and over again, known as an Event Loop.

Synchronization taskThe queuing task on the main thread can be executed only after the previous task is completed.Asynchronous tasksThis refers to tasks that do not enter the main thread but enter the “task queue”. The “task queue” notifies the main thread that an asynchronous task is ready to execute.

Macro and micro tasks

This brings us to macro and micro tasks, which are asynchronous tasks. The main differences lie in their execution order, the direction and value of Event Loop.

1. Macro-task

Macro tasks are host-initiated tasks (browser/Node). Include:

  • Synchronized script (overall code)
  • The timer
  • event
  • ajax
  • The callback function
  • Node fs can perform asynchronous I/O operations
  • UI rendering

2. Micro-task

Microtasks refer to tasks initiated by the JS engine. Include:

  • NextTick: API implemented by process.nextTick node, which puts the current task on the main stack to be executed last. When the main stack is finished, nextTick is executed first and then wait for the task in the queue
  • Promise(async/await) : A Promise is not completely synchronous. In a Promise, it is a synchronous task. When a resolve or reject callback is performed, it is an asynchronous operation, and then/catch etc is placed on the microtask queue. Resolve/Reject is called when the main stack is complete
  • MutationObserver: Creates and returns a new MutationObserver, which is called when the specified DOM changes.

3. Mechanics: Micro tasks are bigger than macro tasks

So there’s a mechanism for js async, which is when you encounter a macro task, you execute the macro task, you put the macro task into the eventQueue, and then you execute the micro task, you put the micro task into the eventQueue and the cool thing is, these two queues are not the same queue. When you go out you take the callback from the microtask first, and then you take the macro task callback from the macro task queue. I saw it and I fell for it and the manipulation.


Now let’s go back to the interview questions listed at the beginning of the article, which are executed in this order:

1, the first JavaScript engine will execute a macro task, pay attention to the macro task generally refers to the main code itself, which is the current synchronization code 2, if there are any micro task execution process, it will get added to the task the task queue 3, macro after completion of task execution, the immediate execution of the current in the micro task queue tasks, 4. After the microtask is completed, the next macro task is executed and the cycle continues until the macro task and microtask are empty.

Specifically for this topic, the order of execution is:

First, execute a macro task, that is, all the synchronization codes, and print them in sequence: script start promise1 promise2 script end First, execute the macro task, check the microtask queue, and find: Promise’s then callback function executes the microtask queue immediately. Print: Promise then

Then the next macro task executes the setTimeout callback, printing: setTimeout.

The setTimeout and setInterval callbacks are macro tasks, but the setTimeout and setInterval callbacks belong to the main code.

Similarly, the lines that print promise1 and promise2 are part of the Promise callback, which is executed immediately and synchronously, and therefore part of the trunk code.