In-depth understanding of event loops in JavaScript event-loop

Source: Internet
Author: User
Tags message queue readfile square root

Previous words

This article describes the event loops in JavaScript in detail Event-loop

Thread

JavaScript is a single-threaded language, meaning that you can only do one thing at a time. While this single-threaded feature is relevant to its purpose, as a browser scripting language, JavaScript's primary purpose is to interact with the user, as well as 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?

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 doesn't change the nature of JavaScript single threading

Queued

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

var i, t = date.now () for (i = 0; i < 100000000; i++) {}console.log (Date.now ()-T)//238 

Like above, if the queue is because of the high computational capacity, the CPU is not busy, but also forget

However, if the network request is not appropriate. It is unwise to wait in line for a network-requested resource when it is unpredictable to return.

Synchronous and asynchronous

Therefore, the task is divided into synchronous tasks and asynchronous tasks

Synchronization

If the caller is able to get the expected result (i.e., the expected return value or see the desired effect) when the function returns, then the function is synchronous

Math.sqrt (2); Console.log ('Hi');

When the first function returns, it gets the expected return value: The square root of 2; When the second function returns, you see the expected effect: a string is printed on the console

So the two functions are synchronous.

Asynchronous

If the caller is not able to get the expected result when the function returns, but it needs to be obtained in the future by some means, then the function is asynchronous

Fs.readfile ('foo.txt'UTF8', function (err, data) {    Console.log (data);});

In the above code, we want to fs.readFile read the contents of the file Foo.txt through the function and print it out. But fs.readFile when the function returns, we expect the result to not happen, but to wait until all the files have been read. It could take a long time if the file is large.

So, the Fs.readfile function is asynchronous.

It is because JavaScript is single-threaded, and asynchronous is easy to implement non-blocking, so in JavaScript for time-consuming operations or the operation of uncertain times, the use of asynchronous is a necessary choice

Asynchronous explanation

As you can see from the above, the 异步函数 call is actually done quickly. But there are many steps behind the asynchronous operation, the notification main thread, the main thread call callback function, and so on. We call the whole process 异步过程 . The invocation of an asynchronous function is only a small part of the entire asynchronous process

An asynchronous process is usually this: the main thread initiates an asynchronous request, and the asynchronous task receives the request and tells the main thread that it has received (the asynchronous function returns); The main thread can continue executing the following code while the asynchronous operation begins, and the main thread is notified after execution is completed, and the main thread receives the notification and performs a certain action ( Call callback function)

Therefore, an asynchronous process consists of two features: a registration function and a callback function, where the registration function is used to initiate the asynchronous process, and the callback function is used to process the result

In the following code, where settimeout is the initiating function of the asynchronous procedure, FN is the callback function

);

There is a very important question, how is an asynchronous operation done? For different types of asynchronous tasks, the standard of operation completion is different

"Asynchronous Type"

Generally, there are three types of asynchronous tasks:

1, ordinary events, such as click, resize, etc.

2. Loading of resources, such as load, error, etc.

3, timers, including setinterval, settimeout, etc.

The following are examples of these three types, the following code, the mouse click on the div, the task execution is completed

Div.onclick = () = {  console.log ('click')}

In the following code, the readystate value of the Xhr object is 4, which means that all response data has been received, representing the completion of the task execution

Xhr.onreadystatechange = function () {  if4) {      if {          // actual operation          result.innerhtml + = xhr.responsetext;   }}}

The following code, after 1s, represents the completion of a task execution

SetTimeout (() = {  console.log ('timeout')},  +)

For synchronous tasks, it can be executed sequentially, but for asynchronous tasks, each task executes differently and the point in time of execution is different, how does the main thread regulate asynchronous tasks? This is where Message Queuing is used.

"Message Queuing"

Some articles call Message Queuing a task queue, or an event queue, in short, a queue that is related to an asynchronous task

To be sure, it is the first-in, first-out data structure of the queue, and the queue is similar, and which asynchronous operation is completed early, is in front. Whenever an asynchronous operation starts executing, it can be queued to the message queue as long as the asynchronous operation completes

This allows the main thread to get a message from the message queue and execute it when it is idle

What exactly is the message in Message Queuing? The concrete structure of the message is of course related to the specific implementation. But for the sake of simplicity, it can be assumed that the message is the callback function that was added when registering the asynchronous task.

Visual description

The mechanism by which JavaScript regulates synchronous and asynchronous tasks is called event loops, and the visual description of the event loop mechanism is first seen

Stack

A function call forms a stack frame

function Foo (b) {  var a = ten;  Return a + B + one;} function bar (x) {  var y = 3;  return foo (x * y);} Console.log (Bar (7));   

When called bar , the first frame is created, bar and the arguments and local variables are included in the frame. When bar called foo , the second frame is created and pressed onto the first frame, and the frame contains foo the parameters and local variables. When foo returned, the topmost frame is ejected from the stack ( bar the call frame of the function is left). When you bar return, the stack is empty.

Heap

Objects are allocated in a heap, which is used to represent a large part of a non-structured memory area

Queue

A JavaScript runtime contains a pending message queue. Each message is associated with a function. When the stack has enough memory, a message is fetched from the queue for processing. This process involves invoking the function associated with the message (and thus creating an initial stack frame). When the stack is empty again, it means that the message processing is over.

Event Loops

The following is a detailed description of the event loop. , when the main thread runs, the heap and stack are generated, the code in the stack calls various external APIs, and after the asynchronous operation completes, it is queued in the message queue. As soon as the code in the stack finishes executing, the main thread reads the message queue and executes the callback function that corresponds to the asynchronous task in turn.

The detailed steps are as follows:

1. All synchronization tasks are performed on the main thread to form an execution stack

2. There is also a "message queue" outside the main thread. Queues the message queue as long as the asynchronous operation finishes executing

3, once all synchronization tasks in the execution stack are executed, the system reads the asynchronous task in the message queue sequentially, and the asynchronous task is read to end the waiting state, enter the execution stack, and start executing

4, the main thread constantly repeat the third step above

Cycle

From the point of view of code execution order, the program first executes code in code order, encounters a synchronization task, executes immediately, and encounters an asynchronous task that simply invokes an asynchronous function to initiate an asynchronous request. At this point, the asynchronous task begins an asynchronous operation that is queued in the message queue after execution completes. After the program executes in code order, query the message queue for waiting messages. If so, the messages are placed in the execution stack from the message queue in order. Once executed, the message is then retrieved from the message queue and then executed and repeated repeatedly.

Because the main thread is repeatedly getting the message, executing the message, then fetching the message, and then executing. So, this mechanism is called the event loop

This is probably the case with code:

while (Queue.waitformessage ()) {  queue.processnextmessage ();}

If no messages are currently queue.waitForMessage waiting for the synchronization message to arrive

Event

Why is it called an event loop? Instead of a task loop or message loop. The reason is that each message in the message queue actually corresponds to an event

Dom operations correspond to DOM events, and the resource load operation corresponds to the Load event, and the timer operation can be seen as a corresponding "time-to-go" event

Instance

An example is given below to explain the event loop mechanism.

Console.log (1= () = {Console.log ('click')}console.log ( 2  = = {Console.log ('timeout')}, +)

1, executes the first line of code, the first line is a synchronization task, console display 1

2, executes the second line of code, the second line is an asynchronous task, initiates an asynchronous request, can perform a mouse click at any time asynchronous operation

3, executes the third line of code, the third line is a synchronization task, console display 2

4, executes the fourth line of code, line fourth is an asynchronous task, initiates an asynchronous request, executes a timer task after 1s

5, assume that the execution of the fourth line of code in 1s, the mouse click, the task in the message queue to the first

6, from the execution of the fourth line of code 1s, the timer task to the message queue to the second place

7. Now that the synchronization task is completed, the asynchronous task is placed in the execution stack from the message queue in the order of execution

8. The console displays ' click ', ' Timeout ' in turn

9, after a period of time, and executed a mouse click, because the message queue is empty, the mouse task in the message queue to the first

10. After the synchronization task is executed, the asynchronous task is placed in the execution stack from the message queue in the order of execution.

11. The console displays ' click '

"Asynchronous Process"

The following is an example to explain a complete asynchronous process

Div.onclick = function fn () {Console.log ('click')}

1. The main thread initiates an asynchronous request by calling the asynchronous function Div.onclick

2, in a moment, perform an asynchronous operation, that is, the mouse click

3. Next, the callback function fn is queued in the message queue

4. The main thread reads FN from the message queue to the execution stack

5. Then execute the Code console.log (' click ') inside FN on the execution stack

6, then, the console display ' click '

Synchronous variable Asynchronous

After each message is fully executed, other messages are executed. This provides some excellent features, including that it cannot be preempted whenever a function is run, and runs completely before other code runs

One drawback of this model is that when a message takes too long to complete, the Web app cannot handle the user's interactions, such as tapping or scrolling

As a result, a common optimization for this situation is synchronous asynchronous

An example is to create a WEBQQ QQ friends list. There are usually hundreds or thousands of friends in the list, and if a friend is using a node to render the list in a page, you might want to create hundreds or thousands of nodes in the page at once.

Adding DOM nodes to a page in a short period of time will obviously make the browser too much, and the results are often the result of browser lag or even suspended animation. The code is as follows:

varary = []; for(vari =1; I <= +; i++) {Ary.push (i); //Suppose ary loaded 1000 friends ' data};varRenderfriendlist =function (data) { for(vari =0, L = data.length; I < L; i++ ){    vardiv = document.createelement ('Div' ); Div.innerhtml=i;  Document.body.appendChild (DIV); }};renderfriendlist (ary);

One solution to this problem is the array chunking technique, where the following Timechunk function allows the creation of nodes to be done in batches, such as creating 1000 nodes in 1 seconds, instead of creating 8 nodes every 200 milliseconds

function Chunk (array,process,context) {    setTimeout (function () {        /// Remove the next entry and process        var item = array.shift ();        Process.call (Context,item);         // If you have an entry, set another timer        if 0 {            setTimeout (Arguments.callee);    }};    
 var  data = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0  ];function Printvalue (item) { var  div = document.getElementById ( "  '  ); div.innerhtml  + = Item +  " <br>   " ;} Chunk (Data.concat (), printvalue);  

The importance of array chunking is that it can separate the processing of multiple items on the message queue, giving other asynchronous task execution opportunities after each item is processed, which may prevent long-running script errors. Once a function takes more than 50ms of time to complete, it's best to see if you can split the task into a series of small tasks that use timers

In-depth understanding of event loops in JavaScript 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.