JavaScript running mechanism of event loop (events Loop) detailed _javascript tips

Source: Internet
Author: User
Tags setinterval

One, why is JavaScript a single thread?

One of the main features of JavaScript language is single-threaded, that is, one thing at a time. So why can't javascript have multiple threads? This will improve efficiency.

A single thread of JavaScript, which is related to its purpose. As a browser scripting language, the main purpose of JavaScript is to interact with the user and manipulate the DOM. This determines that it can only be single-threaded, or it can create 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 another thread deletes the node, which thread should the browser use?
Therefore, in order to avoid complexity, from the birth, JavaScript is a single thread, which has become the core characteristics of the language, will not change in the future.

To take advantage of the computational power of multi-core CPUs, HTML5 proposes web worker standards that allow JavaScript scripts to create multiple threads, but the child threads are completely controlled by the main thread and must not manipulate the DOM. So, the new standard doesn't change the nature of JavaScript single-threaded threads.

Second, the task queue

A single thread means that all tasks need to be queued and the previous task is completed before the latter task is performed. If the previous task takes a long time, the latter task will have to wait all the time.

If the queue is because of the large amount of calculation, CPU busy, but also forget, but many times the CPU is idle, because the IO device (input) is very slow (such as AJAX operations from the network to read data), had to wait for the results out, and then down.

The designer of the JavaScript language realizes that the CPU is fully capable of suspending tasks that are in the waiting position, regardless of IO devices, and running the tasks that are left behind. Wait until the IO device returns the result, and then go back to the pending task.

As a result, JavaScript has two ways to perform: one is to execute the CPU sequentially, the previous task is over, then the next task, which is called synchronous execution, the other is the CPU skips the long wait time task, first processing the later task, which is called asynchronous execution. The programmer chooses what kind of execution to use.

Specifically, the operating mechanism for asynchronous execution is as follows. (This is also true for synchronous execution, because it can be considered asynchronous execution without an asynchronous task.) )

(1) All tasks are executed on the main thread, forming an execution stack (execution context stack).
(2) There is also a "task queue" in the main thread. The system puts the asynchronous task in the task queue, and then continues to perform subsequent tasks.
(3) Once all the tasks in the execution stack have been completed, the system reads the task queue. If this time, the asynchronous task has ended the wait state, it will go from the "task queue" to the execution stack and resume execution.
(4) The main thread continues to repeat the third step above.

The following figure is a schematic diagram of the main thread and the task queue.

As long as the main line Cheng, it will read "task queue", which is the operating mechanism of JavaScript. This process will continue to repeat itself.

III. events and Callback functions

A "task queue" is essentially a queue of events (also understood as a queue of messages), the IO device completes a task, and an event is added to the task queue to indicate that the relevant asynchronous task can enter the execution stack. The main thread reads "Task queue", which is what events are read inside.

Events in the task queue, in addition to events for IO devices, include some user-generated events (such as mouse clicks, page scrolling, and so on). As long as the callback function is specified, these events enter the task queue when they occur, waiting for the main thread to read.

The so-called "callback function" (callback) is the code that will be hung by the main thread. The asynchronous task must specify a callback function, and the callback function executes when the asynchronous task returns from the task queue to the execution stack.

A "task queue" is a first-in, first-out data structure, preceded by an event that first returns the main thread. The main thread reading process is basically automatic, as long as the execution stack is emptied, the first event on the task queue automatically returns to the main thread. However, due to the existence of the "timer" function mentioned above, the main thread should check the execution time, some events must return the main thread at the specified time.

Four, the Event Loop

The main thread reads events from the task queue, and the process is cyclical, so the entire operation is called the event loop.

To better understand the event Loop, look at the figure below (quoted from Philip Roberts ' help, I ' m stuck in a event-loop).

In the diagram above, when the main thread runs, the heap (heap) and stack (stack) are generated, and the code in the stack invokes various external APIs that include various events (Click,load,done) in the task queue. As soon as the code in the stack is finished, the main thread reads the task queue and executes the callback function for those events in turn.

Executes the code in the stack, which is always performed before the task queue is read. Take a look at the example below.

Copy Code code as follows:

var req = new XMLHttpRequest ();
Req.open (' get ', url);
Req.onload = function () {};
Req.onerror = function () {};
Req.send ();

The Req.send method in the above code is that AJAX operations send data to the server, which is an asynchronous task, meaning that the system will read the task queue only if all the code for the current script has finished executing. Therefore, it is equivalent to the following wording.
Copy Code code as follows:

var req = new XMLHttpRequest ();
Req.open (' get ', url);
Req.send ();
Req.onload = function () {};
Req.onerror = function () {};

That is, specifying the parts of the callback function (onload and onerror) is irrelevant before or after the Send () method because they are part of the execution stack, and the system always finishes them before reading the task queue.

Five, timer

In addition to placing an asynchronous task, the task queue has the function of placing a timed event that specifies how long some code will be executed. This is called the timer function, which is the code that executes regularly.

The function of the timer is mainly performed by settimeout () and SetInterval (), and their internal operating mechanism is exactly the same, except that the code specified by the former is executed once and the latter is executed repeatedly. 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.

Copy Code code as follows:

Console.log (1);
settimeout (function () {Console.log (2);},1000);
Console.log (3);

The result of the above code is 1,3,2, because settimeout () delays the second row to 1000 milliseconds after execution.

If the second argument to SetTimeout () is set to 0, the callback function specified (0 millisecond interval) is executed immediately after the current code finishes (execution stack emptying).

Copy Code code as follows:

settimeout (function () {console.log (1);}, 0);
Console.log (2);

The results of the above code are always 2,1, because only after the second row is executed does the system perform the callback function in the task queue.
The HTML5 standard sets the minimum (shortest interval) of the second parameter of settimeout () to be less than 4 milliseconds, and automatically increases if it is below this value. Prior to this, older browsers set the minimum interval to 10 milliseconds.

In addition, changes to those DOM, especially those that involve page rendering, are usually not performed immediately, but are performed 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 the main thread does not execute the callback function it specifies until the current code (the execution stack) has been executed. If the current code takes a long time, it may have to wait long, so there is no way to guarantee that the callback function must be executed at the settimeout () specified.

Vi. the event Loop of Node.js

Node.js is also a single-threaded event Loop, but its operating mechanism is different from the browser environment.

Take a look at the schematic below (author @busyrich).

According to the above figure, the operating mechanism of Node.js is as follows.

(1) The V8 engine parses JavaScript scripts.
(2) The parsed code calls the node API.
(3) The LIBUV Library is responsible for the execution of the node API. It assigns different tasks to different threads, forming an event loop (the loop of events) that 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 settimeout and SetInterval methods, Node.js also provides two other methods related to the task queue: Process.nexttick and Setimmediate. They can help us deepen our understanding of "task queues."

The Process.nexttick method can trigger a callback function----the end of the current execution stack----the next time the main thread reads the task queue. In other words, the task it specifies always occurs before all asynchronous tasks. The Setimmediate method triggers the callback function at the end of the current task queue, which means that the task it specifies is always performed the next time the main thread reads the task queue, much like settimeout (FN, 0). Take a look at the following example (via StackOverflow).

Copy Code code as follows:

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 code above, because the callback function specified by the Process.nexttick method is always triggered at the end of the current execution stack, not only function A is executed in the callback function specified by the settimeout, but also function B is executed before the timeout. This means that if there are multiple Process.nexttick statements, whether they are nested or not, all will be performed on the current execution stack.

Now, look at Setimmediate again.

Copy Code code as follows:

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 code above, there are two setimmediate. The first setimmediate specifies that the callback function is triggered at the end of the current task queue (next event loop), and then settimeout is also specified to trigger the callback function TIMEOUT at the end of the current task queue, so the output is TIMEOUT Fired in the back of 1. As for the 2 row behind timeout fired, it is because of another important feature of Setimmediate: an "event loop" can only trigger a callback function specified by Setimmediate.

We get an important difference: multiple Process.nexttick statements are always executed at once, and multiple setimmediate can be executed several times. In fact, that's why Node.js version 10.0 adds the Setimmediate method, otherwise recursive calls like the following process.nexttick will be endless, and the main thread will not read "event queues" at all!

Copy Code code as follows:

Process.nexttick (function foo () {
Process.nexttick (foo);
});

In fact, now if you write a recursive process.nexttick,node.js you will throw a warning and ask you to change to Setimmediate.
In addition, because the callback function specified by Process.nexttick is triggered in this "event loop", and Setimmediate specifies the next "event loop" trigger, it is obvious that the former always occurs earlier than the latter and performs efficiently (because the task queue is not checked).

Related Article

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.