English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
This article introduces the JavaScript timing mechanism, and to understand the JavaScript timing mechanism, it is necessary to know the JavaScript execution mechanism.
Firstly, it should be declared that JavaScript runs on a single thread (JavaScript engine thread) and is event-driven.
First, there are multiple threads in the browser
The most basic threads included in a browser:
1JavaScript engine thread.
2Timer thread, setInterval and setTimeout trigger this thread.
3Browser event triggering thread, which triggers events such as onclick, onmousemove, and other browser events.
4Interface rendering thread, responsible for rendering HTML elements of the browser interface. Note: During the execution of JavaScript scripts, the interface rendering thread is in a suspended state. That is to say, when JavaScript is used to operate nodes in the interface, it will not be reflected immediately, but only when the JavaScript engine thread is idle will it be reflected. (This is said last)
5HTTP request thread (Ajax requests are included as well).
These threads, under the control of the browser kernel, cooperate with each other to complete their work (specifically, I don't know).
Second, task queue
We know that JavaScript is single-threaded, and all JavaScript code runs in the JavaScript engine thread. Mr. Ruan Yifeng's article calls this thread the main thread, which is an execution stack. (The following content is mainly based on Mr. Ruan Yifeng's article for understanding and summarizing.)
These JavaScript codes can be regarded as individual tasks, which are divided into synchronous tasks and asynchronous tasks. Synchronous tasks (such as variable assignment statements, alert statements, function declaration statements, etc.) are executed in order on the main thread, while asynchronous tasks (such as various events triggered by browser event threads, server responses returned by Ajax, etc.) are queued in the task queue (also known as the event queue or message queue) in chronological order, waiting to be executed. Once the tasks on the main thread are completed, it will check the task queue to see if there are any tasks waiting to be executed, and if there are, let the queued tasks enter the main thread to be executed.
For example, the following example:
<!DOCTYPE html> <html> <head> <meta charset="utf-8">-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Timing Mechanism</title> <style type="text/css"> body{ margin: 0; padding: 0; position: relative; height: 600px; } #test{ height: 30px; width: 30px; position: absolute; left: 0; top: 100px; background-color: pink; } </style> </head> <body> <div id="test"> </div> <script> var pro = document.getElementById('test'); pro.onclick = function() { alert('I was not executed immediately.'); }; function test() { a = new Date(); var b=0; for(var i=0;i<3000000000;i++) { b++; } c = new Date(); console.log(c-a); } test(); </script> </body> </html>
In this example, the test() function needs to be executed for about8~9seconds, so when we open this page, in8times before clicking the pink block, the prompt box will not pop up immediately, but will wait until8seconds later, and also8times before clicking the pink box,8seconds later, pop up several times.
When we open this page, the main thread first declares the function test, then declares the variable pro, assigns the p node to pro, adds a click event to the p node and specifies the callback function (suspended), then calls the test function and executes the code within it. During the execution of the code in the test function, we clicked the p node, and the browser event triggering thread detected this event, placed this event in the task queue so that when the task on the main thread (here is the test function) is completed, it will check the task queue and find this event and execute the corresponding callback function. If we click multiple times, these multiple triggered events will be queued in the task queue in the order of their triggering time (you can add a click event to another element and click different elements alternately to verify).
Below is a summary of the operation mechanism of tasks:
The operation mechanism of asynchronous execution is as follows. (Synchronous execution is the same, because it can be regarded as asynchronous execution without asynchronous tasks.)
1All synchronous tasks are executed on the main thread, forming an execution stack (execution context stack).
2In addition to the main thread, there is also a "task queue" (task queue). As soon as the asynchronous task has a running result, an event is placed in the "task queue".
3Once all the synchronous tasks in the "call stack" are completed, the system will read the "task queue" to see which events are inside. Then, these corresponding asynchronous tasks will end their waiting state, enter the call stack, and start execution.
4The main thread continuously repeats the above third step.
Three, Events and Callback Functions
When we specify an event for a DOM element, we will specify a callback function so that the corresponding code can be executed when the event actually occurs.
The callback function of the event in the main thread will be suspended, and if there is a corresponding event in the task queue, the main thread will execute the corresponding callback function when it detects it. We can also say that the main thread executes asynchronous tasks by executing the corresponding callback functions.
Four, Event Loop
The process of the main thread checking the event queue is a continuous loop, so we can draw a diagram of an event loop:
In the figure above, the main thread generates the heap and executes the call stack. After the tasks in the stack are executed, the main thread checks the events passed into the task queue by other threads, detects the event at the front of the queue, finds the corresponding callback function from the suspended callbacks, and then executes it in the call stack. This process repeats.
Five, Timer
With the above knowledge, let's discuss the timers setTimeout() and setInterval() in JavaScript.
setTimeout(func, t) is a timeout call, calling the function after a certain interval. The process in the event loop is as follows (my understanding):
After the main thread executes the statement setTimeout(func, t);, it suspends the callback function func, and the timer thread starts timing. When the timing equals t, it is equivalent to an event occurring, which is passed into the task queue (stop timing, only time once), and when the main thread finishes executing the tasks, the main thread checks the task queue and finds this event, then executes the suspended callback function func. The time interval t we specify is just a reference value, and the actual time interval depends on the time taken by the code executed after the statement setTimeout(func, t);, and it is only larger or equal. (Even if we set t to 0, we still have to go through this process).
setInterval(func, t) is an interval call, calling the function at regular intervals. This process in the event loop is similar to the above but also different.
setTimeout() adds an event (note that it is one) to the task queue after a time t has passed (the timer thread adds an event to the task queue every time t passes, regardless of whether the previously added event has been detected and executed by the main thread). (In fact, browsers are quite intelligent. When processing setInterval, if the browser finds that there is already a queued setInterval interval call event with the same ID in the task queue, it will directly kill the new event. That is to say, only one event from the same ID can exist in the task queue at a time.)
For example, if the code after executing setInterval(func, t); takes2At the time of t, when2After t time, the main thread detects the first interval call event passed from the timer thread to the task queue, and the func starts executing. After the first func execution is completed, the second interval call event has already entered the task queue, and the main thread immediately detects the second interval call event, and the func function executes immediately again. In this case, the two executions of the func function are consecutive without any time interval in between.
Here is an example:
function test() { a = new Date(); var b=0; for(var i=0;i<3000000000;i++) { b++; } c = new Date(); console.log(c-a); } function test2() { var d = new Date().valueOf(); //var e = d-a; console.log('The moment I was called is: '+d+,'ms'); //alert(1); } setInterval(test2,3000); test();
Result:
Why8.6seconds after which there is no output of two identical moments, the reason for which can be found in the content above.
the for loop in the example takes8601ms, during the execution of the for loop, there is only one intermittent call event queuing up in the queue (the reason is as described above), when8601ms after, the first intermittent call event enters the main thread. For this example, at this point the task queue is empty, and another intermittent call event can be passed in, so1477462632228ms at this moment, the second intermittent call event (which should actually be the third) is passed into the task queue, since the execution stack of the main thread is empty, the main thread immediately takes the corresponding callback function to execute, and the interval between the second and the first call is only320ms (actually8601+320=8920, which is almost equal to9seconds). We can see that the third call has returned to normal because there is no other code in the main thread at this point, just one task, which is to execute the callback function of the intermittent call at regular intervals.
Example of implementing an intermittent call with setTimeout():
function test() { a = new Date(); var b=0; for(var i=0;i<3000000000;i++) { b++; } c = new Date(); console.log(c-a); } function test2(){ var d = new Date().valueOf(); console.log('The moment I was called is: '+d+,'ms'); setTimeout(test2,3000); } setTimeout(test2,3000); test();
Result:
The time interval between each call is basically the same. Think about why?
Let's look at another example:
<!DOCTYPE html> <html> <head> <meta charset="utf-8">-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Flex Layout Practice</title> <style type="text/css"> body{ margin: 0; padding: 0; position: relative; height: 600px; } #test{ height: 30px; width: 30px; position: absolute; left: 0; top: 100px; background-color: pink; } </style> </head> <body> <div id="test"> </div> <script> var p = document.createElement('p'); p.style.width = '50px'; p.style.height = '50px'; p.style.border = '1px solid black'; document.body.appendChild(p); alert('ok'); </script> </body> </html>
The result of this example is that the prompt box pops up first, and then the black border p element appears on the page. The reason is very simple, just one sentence:
During the execution of the script by the JavaScript engine, the rendering thread of the interface is in a suspended state. That is to say, when JavaScript is used to operate nodes in the interface, it will not be reflected immediately. It will only be reflected when the JavaScript engine thread is idle.
This is my understanding and summary of JavaScript's timing mechanism. If there are any mistakes, I hope the greats who see it can point them out. Also, I hope everyone will support and cheer for the tutorial.
Statement: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please report violations by email to codebox.com (replace # with @ in the email address) and provide relevant evidence. Once verified, this site will immediately delete the infringing content.