This article turns from Ruan Yi Feng Great god
" Personal Understanding point:"
1. The task queue is the queue for an event, as long as the event specifies a callback function that, when the event completes the task, adds an event to the task queue, waiting for the main thread to read.
2. After the main thread executes the synchronization task in the "Execution stack", go to start executing the asynchronous task that has completed the task waiting, execute the task corresponding callback function
3. The main thread of the reading process is basically automatic, as long as the execution stack is emptied, the first event on the "task queue" automatically enters the main thread (timer to the specified time, to return to the main thread)
4. An asynchronous task means that the system will not read the task queue until all the code for the current script is executed
5. Perform the main thread first (the synchronization task is placed in the main thread), the main thread executes, the system goes to read the task queue (the asynchronous task is placed in the task queue)
Read Catalogue
- Begin
- Why is JavaScript a single thread?
- Second, the task queue
- III. events and Callback functions
- Iv. Event Loop
- Five, timer
- Vi. event Loop for node. js
Philip Roberts's speech, "help, I ' stuck", describes the internal operating mechanism of the JavaScript engine in a detailed, complete, and correct manner.
Back to top one, why is JavaScript single-threaded?
One of the main features of the JavaScript language is single-threaded, meaning that only one thing can be done at the same time. So why can't javascript have multiple threads? This can improve the efficiency AH.
The single thread of JavaScript is related to its purpose. As a browser scripting language, JavaScript's primary purpose is to interact with the user and manipulate the DOM. This determines that it can only be single-threaded, otherwise it can lead to complex synchronization problems. For example, assuming that JavaScript has two threads at the same time, one thread adds content to one of the DOM nodes, and the other thread deletes the node, which thread should the browser take precedence over?
So, to avoid complexity, JavaScript is a single thread from birth, which has become a core feature of the language and will not change in the future.
To take advantage of the computational power of multicore CPUs, HTML5 proposes a web worker standard that allows JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and must not manipulate the DOM. So, this new standard does not change the nature of JavaScript single threading.
Back to top second, task queue
A single thread means that all tasks need to be queued, and the previous task is completed before the latter one is executed. If the previous task takes a long time, the latter task has to wait.
If the queue is because of large computational capacity, the CPU is not busy, but also forget, but many times the CPU is idle, because the IO device (input) is very slow (such as the Ajax operation from the network to read data), have to wait for the results, and then down to execute.
The designer of the JavaScript language realizes that at this point the main thread can completely ignore the IO device, suspend the waiting task, and first run the task that is in the queue. Wait until the IO device returns the result, and then go back and put the suspended task on hold.
Thus, all tasks can be divided into two types, one synchronization task (synchronous) and one asynchronous task (asynchronous). A synchronization task is a task that is queued on the main thread to perform the latter task only if the previous task is completed, and the asynchronous task refers to a task that goes into the task queue without entering the main thread, and only the task queue notifies the main thread that an asynchronous task can execute. The task will not go into the main thread execution.
Specifically, the operating mechanism for asynchronous execution is as follows. (Synchronous execution is also true because it can be treated as asynchronous execution without an asynchronous task.) )
(1) All synchronization tasks are performed on the main thread, forming an execution stack (execution context stack).
(2) In addition to the main thread, there is a task queue. As long as the asynchronous task has a running result, an event is placed in the task queue.
(3) Once all the synchronization tasks in the "execution stack" have been executed, the system reads the "task queue" to see what events are in it. Those corresponding asynchronous tasks, so end the wait state, go to the execution stack, and start execution.
(4) The main thread constantly repeats the third step above.
is the main thread and the task queue.
As long as the main line Cheng, will read "task queue", this is the operation mechanism of JavaScript. This process is repeated.
Back to top three, events and callback functions
The task queue is a queue of events (which can also be understood as a queue of messages), and the IO device completes a task by adding an event in the task queue that indicates that the associated asynchronous task can enter the execution stack. The main thread reads the "Task queue", which is what events are read inside.
Events in the task queue, in addition to the IO device events, include some user-generated events (such as mouse clicks, page scrolling, and so on). Whenever a callback function is specified, these events go into the task queue and wait for the main thread to read.
The so-called "callback function" (callback) is the code that will be hung up by the main thread. An asynchronous task must specify a callback function that executes the corresponding callback function when the main thread starts executing an asynchronous task.
A "task queue" is a FIFO data structure, preceded by events, that are first read by the main thread. The main thread of the read process is basically automatic, as long as the execution stack is emptied, the first event on the "task queue" automatically enters the main thread. However, due to the "timer" feature mentioned later, the main thread must first check the execution time, and some events will return to the main thread only by the specified time.
Back to top four, Event Loop
The main thread reads events from the task queue, and the process is cyclic, so the whole mechanism is called event loop.
To get a better understanding of the event Loop, see (quoted from Philip Roberts's speech, "Help, I ' m stuck and an Event-loop").
, when the main thread runs, the heap (heap) and stack (stack) are generated, and the code in the stack calls various external APIs, which include various events (Click,load,done) in the task queue. As soon as the code in the stack finishes executing, the main thread reads the task queue and executes the callback function that corresponds to those events.
The code in the execution stack (the synchronization task) is always executed before the task queue (asynchronous task) is read. Take a look at the example below.
varReq= New XMLHttpRequest();Req.Open( ' GET ',Url);Req.OnLoad= function (){};Req.OnError= function (){};Req.Send( );
The Req.send method in the above code is that the AJAX operation sends data to the server, which is an asynchronous task that means that the system will not read the task queue until all the code for the current script has been executed. Therefore, it is equivalent to the following notation.
varReq= New XMLHttpRequest();Req.Open( ' GET ',Url);Req.Send( );Req.OnLoad= function (){};Req.OnError= function (){};
That is, specifying the part of the callback function (onload and onerror) does not matter before or after the Send () method, because they are part of the execution stack and the system always executes them before it reads the task queue.
Back to top five, timer
In addition to the events that place an asynchronous task, the task queue can also place timed events that specify how much time some code executes. This is called the timer function, which is the code that executes periodically.
The timer function is mainly by settimeout () and setinterval () These two functions to complete, their internal operation mechanism is exactly the same, the difference is that the former specified code is one-time execution, the latter is repeated execution. The following main discussion settimeout ().
SetTimeout () accepts two parameters, the first is a callback function, and the second is the number of milliseconds to defer execution.
Console.log( 1);setTimeout( function(){Console.log( 2);}, +);Console.log( 3);
The result of the above code is 1,3,2, because settimeout () defers the second line to 1000 milliseconds after execution.
If you set the second parameter of settimeout () to 0, the callback function specified immediately (0 millisecond interval) is executed as soon as the current code finishes executing (execution stack emptying).
settimeout ( function ( { console log 1 0 Console log 2
The result of the above code is always 2,1, because only after the second line is executed will the system execute the callback function in the task queue.
In summary, setTimeout (fn,0) means that a task is specified to execute at the earliest available idle time of the main thread, that is, to execute as early as possible. It adds an event at the end of the task queue, so it will not be executed until both the synchronization task and the task queue existing events are processed.
The HTML5 standard specifies the minimum value (minimum interval) of the second parameter of the settimeout (), which is not less than 4 milliseconds, and is automatically incremented if it is below this value. Prior to this, the older versions of the browser set the minimum interval to 10 milliseconds. In addition, the changes to those dom, especially those involving page re-rendering, are usually not executed immediately, but once every 16 milliseconds. The effect of using requestanimationframe () is better than settimeout ().
It is important to note that setTimeout () simply inserts the event into the "task queue" and must wait until the current code (execution stack) finishes executing, before the main thread executes the callback function it specifies. If the current code takes a long time, it may take a long time, so there is no guarantee that the callback function will be executed at settimeout ().
Back to top six, node. JS's Event Loop
node. JS is also a single-threaded event Loop, but it operates differently from the browser environment.
Take a look at the following (author @busyrich).
According to this, node. JS runs the following mechanism.
(1) V8 engine parsing JavaScript script.
(2) After parsing the code, call the node API.
(3) The LIBUV Library is responsible for node API execution. It assigns different tasks to different threads, forms an event loop, and asynchronously returns the execution results of the task to the V8 engine.
(4) The V8 engine returns the result to the user.
In addition to the two methods of settimeout and SetInterval, node. JS also provides two other methods related to the task queue: Process.nexttick and Setimmediate. They can help us deepen our understanding of the "task queue".
The Process.nexttick method can trigger a callback function----the end of the current execution stack----The next event Loop (the main thread reads the task queue). In other words, it specifies that the task always occurs before all asynchronous tasks. The Setimmediate method adds an event at the end of the current task queue, meaning that the task it specifies is always executed at the next event loop, much like the settimeout (FN, 0). Take a look at the following example (via StackOverflow).
Process.Nexttick( function A( ) {Console.log( 1);Process.Nexttick( function B( ){Console.log( 2);});});setTimeout( function Timeout( ) {Console.log( ' TIMEOUT fired ');}, 0)//1//2//TIMEOUT fired
In the above code, the callback function specified by the Process.nexttick method is always triggered at the end of the current "execution stack", so not only function A is executed before the callback function specified by settimeout, but function B is also executed before timeout. This means that if there are multiple Process.nexttick statements (whether or not they are nested), they will all be executed on the current "execution stack".
Now, look at setimmediate.
setimmediate( function A( ) {Console.log( 1);setimmediate( function B( ){Console.log( 2);});});setTimeout( function Timeout( ) {Console.log( ' TIMEOUT fired ');}, 0);
In the above code, Setimmediate and SetTimeout (fn,0) each added a callback function A and timeout, which are triggered at the next event loop. So, which callback function executes first? The answer is not sure. The result may be 1--timeout fired--2, or a TIMEOUT fired--1--2.
Confusingly, the node. js document says that setimmediate specifies a callback function that always precedes settimeout. In fact, this happens only when a recursive invocation occurs.
setimmediate( function (){setimmediate( function A( ) {Console.log( 1);setimmediate( function B( ){Console.log( 2);});});setTimeout( function Timeout( ) {Console.log( ' TIMEOUT fired ');}, 0);});//1//TIMEOUT fired//2
In the above code, Setimmediate and settimeout are encapsulated in a setimmediate, and its running result is always 1--timeout fired--2, when function A must be triggered in front of TIMEOUT. As for the 2 row behind timeout fired (that is, function B is triggered after timeout), because setimmediate always registers events with the next event loop, so functions A and timeout are executed in the same loop, and function B executes in the next loop.
We get an important difference between Process.nexttick and setimmediate: Multiple Process.nexttick statements are always executed at the current execution stack, and multiple setimmediate may require multiple loops to execute. In fact, this is the reason for the addition of the Setimmediate method to node. JS version 10.0, otherwise recursive calls to Process.nexttick like the following will be endless and the main thread will not read the event queue at all!
Process. Nexttick(functionfoo(){process. Nexttick(foo) ; });
In fact, now if you write a recursive process.nexttick,node.js will throw a warning and ask you to change to Setimmediate.
Also, since the callback function specified by Process.nexttick is triggered in the event loop, and Setimmediate specifies the next "event loop" trigger, it is clear that the former is always older than the latter and the execution is high (because the task queue is not checked).
A detailed description of JavaScript operating mechanism