Introduction
I believe that all the learning of JavaScript know that it is a single-threaded language, which means that JS can not be multithreaded programming, but JS has a ubiquitous asynchronous concept. In the early days, many people will interpret asynchronous as a multithreaded programming model, in fact, there are a lot of differences between them, to fully understand the asynchronous, you need to understand the operation Core JS- event loop. Before I knew about the event loop, I was smattering until I saw Philip Roberts's speech, what's the heck is the event loop anyway? I have a comprehensive understanding of the event loop, so I want to write an article about the JS event loop. , for everyone to learn and reference.
First, why is there asynchronous?
Why is there asynchronous in JS? Let's imagine what would happen if we were to execute the code synchronously:
1 function (data) {2 // Do something 3 });
When we use Ajax to communicate, we all default on it to be asynchronous, but what happens if we set it to execute synchronously? If you write a small test program yourself, delay the background code by 5s and you will notice that the browser will block until the Ajax responds and it will not run properly. This is the first problem that the async pattern solves, and how to make the browser non-blocking running tasks. Imagine that if we synchronously execute an AJAX request, our waiting time is unknown, may be very slow in network communication, and may never respond, which will cause the browser to block on an unknown task, which we do not want to see. So we want to have a way to process the program asynchronously, and we don't have to worry about when an AJAX request will be completed, or even it can never respond, we just need to know what to do with the request response, and we can do some other work while we wait for the response. As a result, JavaScript Event Loop is available.
Second, what is the event queue?
First, let's look at a simple code:
1 console.log ("script Start"); 2 3 setTimeout (function () {4 console.log ("SetTimeout"); 5 }, (+); 6 7 Console.log ("script End");
You can check the results here:
We can see that, first, the program outputs ' script start ' and ' script End', which output ' setTimeout ' after about 1s. The program's ' script end ' does not wait for the output after 1s, but instead outputs it immediately. This is because SetTimeout is an asynchronous function. This means that when we set a delay function, the current script will not block, it will only be recorded in the browser's event table , the program will continue to execute. When the delay time is over, the event table adds the callback function to the event queue ( task queues), the event queue gets the task and then presses the task into the stacks (stack) , performs the stack execution task, outputs ' SetTimeout '.
An event queue is a queue that stores tasks that are to be executed, in which the tasks are executed in chronological order, and the tasks in the team head are taken first, and the tasks at the end of the line are executed at the end. The event queue executes only one task at a time, and then executes the next task after the task has finished executing. The execution stack is a running container similar to the function call stack, and when the execution stack is empty, the JS engine checks the event queue and, if not empty, the event queue presses the first task into the execution stack.
Now, let's make a little change to the above code:
1 console.log ("script start" ); 2 function () { ); 5 }, 0 6 7 console.log ("script End");
Set the delay time to 0 to see in what order the program will output? No matter how much delay time we set,' SetTimeout ' will always output after ' script End '. Some browsers may have a minimum delay time, some 15ms, some 10ms, which is mentioned in many books, this may give the students an illusion: because the program is running fast, and has a minimum delay time, so ' SetTimeout ' will Output after ' script end ' . Now let's change it a little bit to get rid of your illusion:
1Console.log ("Script Start");2 3SetTimeout (function () {4Console.log ("SetTimeout");5}, 0);6 7 //The exact number varies depending on your hardware configuration and the browser8 for(vari = 0; i < 999999999; i + +){9 //Do somethingTen } One AConsole.log ("script End");
You can check the results here:
As you can see, the' setTimeout ' will always output after the ' script End ', no matter how much delayed work we do behind it. So what the hell is going on? This is because SetTimeout's callback function is simply added to the event queue instead of being executed immediately. Because the current task does not end, the SetTimeout task does not execute until the ' script end ' is output, the current task executes and the execution stack is empty, and the event queue pushes the setTimeout callback function into execution stack execution.
The execution stack is like the call stack of a function, which is a tree-like stack:
Iii. What is the role of the event queue?
Through the demo above, I believe the students will have a basic understanding of the event queue and execution stack, so what is the role of the event queue? The easiest thing to understand is the async problem we mentioned earlier. Because JS is single-threaded, synchronous execution of the task will cause the browser to block, so we divide the JS into one task after another, through the continuous loop to perform the task in the event queue. This makes it possible to do something else when we suspend a task, without waiting for the task to complete. Therefore, the operation mechanism of the event loop is broadly divided into the following steps:
- Checks whether the event queue is empty, and if it is empty, resumes checking, or 2 if not empty;
- Take out the header of the event queue and press into the execution stack;
- Perform tasks;
- Check the execution stack, if the execution stack is empty, jump back to the 1th step, or continue checking if not empty;
So far, however, we're just talking about how the JS engine executes the JS code, and now we're going to talk about the role of event loops in conjunction with Web APIs.
At the beginning we discussed the asynchronous and synchronous nature of Ajax technology, and through the event loop mechanism, we don't have to wait for the Ajax response to work. We are setting up a callback function, suspending the AJAX request, and continuing with the subsequent code, as to when the request responds, it has no effect on our program, or even it may never respond or block the browser. When the response succeeds, the browser's event table adds the callback function to the event queue for execution. The callback function of the event listener is also a task, when we register an event listener, the browser event table is registered, and when we trigger the event, the event table adds the callback function to the event queue.
We know that DOM operations trigger the browser to render the document, such as modifying the typesetting rules, modifying the background color, and so on, so how does this work in the browser? Now that we know how the event loop is executed, the event Circulator checks the event queue and, if not empty, pulls the team first into the execution stack. Once a task has finished executing, the event Circulator will continue to check the event queue, but in this case, the browser renders the page. This ensures that the user will not appear when browsing the page blocking the situation, which makes the JS animation possible, jQuery animation at the bottom of the use of setTimeout and setinterval to achieve. Imagine that if we were to perform the animation synchronously, we would not see any gradient effect, and the browser would render the window after the task had finished executing. Instead of using asynchronous methods, the browser renders the window at the end of each task execution so that we can see the gradient of the animation.
Consider the following two ways to traverse:
1 vararr =NewArray (999);2Arr.fill (1);3 functionAsyncforeach (array, handler) {4 vart = setinterval (function () {5 if(Array.Length = = 0){6 clearinterval (t);7}Else {8 handler (Arr.shift ());9 }Ten}, 0); One } A - //Asynchronous Traversal -Asyncforeach (arr,function(value) { the Console.log (value); - }); - - //Synchronous Traversal +Arr.foreach (function(value, index, arr) { - Console.log (value); +});
After testing, we can see that the method of synchronous traversal, when the array length rises to 3 digits, there will be blocking, but asynchronous traversal without blocking phenomenon (unless the length of the array is very large, because the computer has insufficient memory space). This is because the synchronous traversal method is a separate task, which iterates through all the array elements before starting the next task. The asynchronous traversal method splits each traversal into a single task, and a task traverses only one array element, so our browser can render between each task, so we don't see the blocking situation. The following demo shows what happens before and after an asynchronous traversal:
Summarize
Now, believe that you know the true face of JavaScript. JavaScript is a single-threaded language, but the nature of its event loop allows us to execute programs asynchronously. These asynchronous programs are a separate task, including SetTimeout, SetInterval, Ajax, EventListener, and so on. On the event loop, we need to keep in mind the following points:
- The event queue presses the task into execution stack strictly in chronological order;
- When the execution stack is empty, the browser keeps checking the event queue and, if not empty, takes out the first task;
- At the end of each task, the browser renders the page;
This paper is placed on the jsfiddle, if you need to reprint, note the source is good. If you find a mistake in this article, please note in the comments section.
In-depth understanding of JavaScript event Loops (i)-event loop