JS's event loop

Source: Internet
Author: User
Tags setinterval

Stacks (Stack)

A stack is a data collection that follows a last-in, first-out (LIFO), and the newly added or deleted elements are stored at the end of the stack, called the top of the stack, and the other end is called the bottom of the stack. In the stack, the new elements are near the top of the stack, and the old elements are close to the bottom.

The feeling is not very good understanding, we give an example, for example, there is a ping-pong box, we keep the ball box into the table tennis, then the first put in the table tennis must be at the bottom, the last place must be on the top, then if we want to take these balls out, it must be from top to bottom in order to take out , this model is the last-first-out, that is, we get into the ball box is the first to come out.
The concept of the stack is actually very important in our JS, we all know that our JS is a single-threaded language, then he single-threaded where, in his main working thread, which is what we often say the execution context, this execution context is the stack space, we look at a code:
Console.log (' 1 ');
function A () {
Console.log (' 2 ');
Function B () {
Console.log (' 3 ')
}
B ()
}
A ()

Copy the code we know that when the function is executed, the function is put into our execution context, and the execution stack pops up when the function is executed, so we can see that the code is running as

First of all, we have a global context for code execution, where the code runs, the global context executes the stack, and it's at the bottom of the stack.
We encounter Console.log (' 1 '), this function at the time of the call into the execution stack, when this sentence execution is finished to the next line when the console this function will be out of the stack, the stack is still only the global context
Then run the code, it is noted that we encounter the function of the declaration will not go into the execution stack, only when our function is called to be executed when it will enter, this principle and we execute the stack name is exactly the same, then we encountered a (), this code this time our a function entered the execution stack, And then into the inside of our function of a, where our function execution stack should be the global context--a
Then I run Console.log (' 2 '), the execution stack becomes the global context--a--console, and then our console runs and our execution stack reverts to the global context--a
Then we ran into B (), then B went into our execution stack, the global context--a--b,
Then enter the interior of the B function, execute Console.log (' 3 ') when the execution stack is the global context--a--b--console, after the completion of the reply to the global context--a--b
Then our B function is executed, then the execution stack is ejected, then the execution stack becomes the global context--a
Then our a function is executed and then the execution stack is popped, then the execution stack becomes the global context
Then our global context will be out of the stack when our browser closes

The execution of our execution context is like this, is not clear a lot ~
We can find several features through the execution context above:

Execution context is single thread
Execution context is synchronous execution of code
When a function is called, the function goes into the execution context
The execution of the code produces a global context, and only when the browser is closed will the stack

Queuing (queue)

A queue is a collection of data that follows a first-in, in-Advance (FIFO), and new entries are added to the end of the queue, and the old entries are removed from the head of the queue.

Here we can see the queue and the stack is different where the stack is a last-first-out similar to a ping-pong box, and the queue is FIFO first, that is, the first entry will go out first.
Similarly, we give an example, the queue is like we line up security, the first to come to the ranks of the first, then the people then ranked in the back of the team, and then the security officer will be from the first end of the team to carry out security screening, a person to check out a person, is not such a team is a first-out process.
Queue here we are going to mention two concepts, the macro task, the Micro task.
Task Queue
JS event execution is divided into macro-benevolence and micro-tasks

Grace services are mainly composed of script (Global Task), SetTimeout, SetInterval, setimmediate, I/O, UI rendering
Micro-tasks are mainly Process.nexttick, Promise.then, Object.observer, Mutationobserver.

Browser event Loop
JS executes the code in the process if you encounter the above task code, the callback will be placed in the corresponding task queue, and then continue to execute the main thread of the code to know that the execution context of the function is complete, will go to the Micro task queue to perform related tasks, the Micro task queue after the cleanup, Take the task out of the macro-benevolence queue into the execution context, and then continue the loop.

Execute code, encountered macro benevolence into the macro benevolence queue, encountered micro-task into the micro-task queue, execute other functions when the execution context
Performs a micro-task queue after all execution in the execution context is completed
After the micro-task queue is executed, the first item in the macro-benevolence queue is executed in the execution context
And then we keep looping 1-3 steps, which is the JS event loop in the browser environment.

//学了上面的事件环 我们来看一道面试题setTimeout(function () {  console.log(1);}, 0);Promise.resolve(function () {  console.log(2);})new Promise(function (resolve) {  console.log(3);});console.log(4);//上述代码的输出结果是什么???

Copy code think thinking think about thinking ~ ~ ~
The correct answer is 3 4 1, isn't it the same as you think? Let's take a look at the running flow of code
Encounter SetTimeout put settimeout callback into the macro benevolence queue
SetTimeout (function () {
Console.log (1);
}, 0);
Encountered a promise, but there is no then method callback so this code will go into our current execution context in the execution process immediately after the stack
Promise.resolve (function () {
Console.log (2);
})
Met a new Promise, I do not know whether we remember the last article on the Promise there is a principle is that when initializing Promise Promise The constructor function will be executed immediately so here will immediately output a 3, So this 3 is the first one to enter.
New Promise (function (resolve) {
Console.log (3);
});
Then enter the second output 4 when the code executes to go back to the micro-task queue to find there is no task, found that the micro-task queue is empty, then go to the macro-benevolence queue to find, found that we have just put in the settimeout callback function, then take out this task to execute, so immediately after the output 1
Console.log (4);
Copy the code to see the above explanation, we are not all understand, is not straight call simple ~
So let's take a look at the event execution ring in the node environment.
NodeJs Event Ring
The browser's event loop follows the HTML5 standard, and NodeJs's event loop follows the LIBUV standard, so there will be a certain difference in the execution of the event, we all know that NodeJs is actually a runtime of JS, that is, the operating environment, then In this environment, most of the Nodejs API is executed through callback functions, the way events are published and subscribed, so what is the order of execution of our code in such an environment, that is, how our different callback functions are categorized and then executed in what order, In fact, it is determined by our LIBUV.
┌───────────────────────────┐
┌─>│timers│
│└─────────────┬─────────────┘
│┌─────────────┴─────────────┐
││pending callbacks│
│└─────────────┬─────────────┘
│┌─────────────┴─────────────┐
││idle, prepare│
│└─────────────┬─────────────┘┌───────────────┐
│┌─────────────┴─────────────┐│incoming:│
││poll│<─────┤connections,│
│└─────────────┬─────────────┘│data, etc.│
│┌─────────────┴─────────────┐└───────────────┘
││check│
│└─────────────┬─────────────┘
│┌─────────────┴─────────────┐
└──┤close callbacks│
└───────────────────────────┘
Copy the code we'll see what these six missions are for.

Timers: This stage performs callbacks set by SetTimeout () and SetInterval ().
Pending callbacks: A small number of I/O callback in the previous cycle will be deferred until this stage of the round is executed.
Idle, prepare: internal use only.
Poll: Performing I/O callback, blocking at this stage under appropriate conditions
Check: Executes the callback set by the Setimmediate ().
Close callbacks: Perform such as Socket.on (' close ', ...) The callback.

We look at the online find a Nodejs execution diagram, we can see that there are six steps in the diagram, when the code execution if we encounter the callback function in the six steps, we put into the corresponding queue, and then when we synchronize the character execution, we will switch to the next stage, that is, the timer stage, Then the timer phase executes all of the callback functions in this phase and then into the next stage, it is important to note that we will be in each phase of the switch to perform a micro task queue of all tasks, and then into the next task phase, So we can summarize the sequence of Nodejs events.

Synchronous code execution, emptying of the micro task queue, execution of the timer stage callback function (i.e. settimeout,setinterval)
Complete execution, empty the Micro task queue, execute pending callbacks phase callback function
Complete execution, empty the Micro task queue, execute idle, prepare phase callback function
Complete execution, empty the Micro task queue, execute the callback function of the poll phase
Execute all, empty the Micro task queue, execute the Check phase callback function (i.e. setimmediate)
Complete, empty the Micro task queue, execute the close callbacks stage callback function
Then loop through 1-6 stages

Then let's practice practiced hand ~ ~ ~
Let's take a look at our implementation phase.
Let FS = require (' FS ');
Encounter settimeout put in timer callback
SetTimeout (function () {
Promise.resolve (). Then (() =>{
Console.log (' then1 ');
})
},0);
Put into the Micro task queue
Promise.resolve (). Then (() =>{
Console.log (' then2 ');
});
I/O operations are placed in the pending callbacks callback
Fs.readfile ('./text.md ', function () {
Put into check stage
Setimmediate (() =>{
Console.log (' setimmediate ')
});
Put into the Micro task queue
Process.nexttick (function () {
Console.log (' Nexttick ')
})
});
Copy code first the synchronization code is finished, we empty the micro task, then output then2, then switch to the timer stage, execute a timer callback, output THEN1, then perform the I/O operation callback, then empty the Micro task queue, output Nexttick, and then into the check phase, Emptying the check stage callback output setimmediate

JS's event loop

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.