A detailed explanation of JavaScript running mechanism: Another talk about event Loop

Source: Internet
Author: User

A year ago, I wrote an article, "What is Event Loop?" , and talked about my understanding of the event loop.

Last month, I happened to see Philip Roberts's speech, "Help, I ' M stuck in an Event-loop". It is only embarrassing to find that their understanding is wrong. I decided to rewrite this topic to describe the internal operating mechanism of the JavaScript engine in a detailed, complete, and correct manner. Here's my rewrite.

Before entering the text, a message is interrupted. My new book "ECMAScript 6 Primer" published (Copyright page, page 1, page 2), coated paper full-color printing, very beautiful, but also with index (of course, the price is slightly more expensive than similar books a little). Preview and purchase click here.

Why is JavaScript a single thread?

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.

Second, the 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 CPU can completely ignore the IO device, suspend the waiting task, and run the task in the queue first. Wait until the IO device returns the result, and then go back and put the suspended task on hold.

Thus, JavaScript has two ways of doing it: the CPU executes sequentially, the previous task ends, and then the next task, which is called synchronous execution, and the CPU skips a long wait task, first processing the later task, which is called asynchronous execution. Programmers choose which method to use.

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 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. The system puts the asynchronous task in the task queue and then resumes the subsequent task.

(3) Once all the tasks in the "execution stack" have been executed, the system reads the "Task queue". If this time, the asynchronous task has completed the wait state, it will go from the "task queue" into the execution stack, resume 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.

III. events and Callback functions

A "task queue" is essentially 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 to the task queue, indicating 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. The asynchronous task must specify a callback function that executes when the asynchronous task returns to the execution stack from the task queue.

A "task queue" is a first-in-one data structure, preceded by an event, that returns the main thread first. The main thread's read 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 "timer" feature mentioned later, the main thread has to check the execution time, and some events must be returned to the main thread at a specified time.

Iv. 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 is always executed before the task queue is read. Take a look at the example below.

    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 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.

    var req = 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.

Five, timer

In addition to placing asynchronous tasks, the task queue also has the function of placing 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);},1000); 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.

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 requestanimframe () 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 ().

Vi. event Loop for node. js

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.

node. JS has a Process.nexttick () method that defers the specified event to the next execution of the event loop, or to the head of the task queue, which is immediately executed after the current execution stack is emptied.

function foo () {    console.error (1);} Process.nexttick (foo); Console.log (2);//2//1

Process.nexttick (foo) is similar to settimeout (foo, 0), but performs much more efficiently.

Author: Ruan Yi Feng

A detailed explanation of JavaScript running mechanism: Another talk about event Loop

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.