Single-threaded JavaScript that executes asynchronously
JavaScript is a single-threaded asynchronous execution, and a single thread means that the code executes one after the other in the task queue. The asynchronous representation of JavaScript code in the task queue is not exactly the same as the order in which the code is written, such as event binding, Ajax, SetTimeout (), and so on, when the task is "not expected".
Since JavaScript is a single threading mechanism, why is Ajax asynchronous? How is the SetTimeout () implemented?
In the browser, the JavaScript engine is single-threaded. That is, at the same time, only one piece of code can be executed by the JavaScript engine. When the page loads, the JavaScript engine executes all the JavaScript code on the page sequentially, prioritizing the synchronization code. Asynchronous code is added to the JavaScript engine's task queue by the event-triggering engine in the order in which the event occurs, and the JavaScript engine executes the asynchronous code in the order of the task queue after all synchronization code execution is complete.
Here is a reply to the above:
JavaScript engines are single-threaded, and browsers run JavaScript programs at all times and only one thread.
The kernel of the browser is multi-threaded, and they mate with each other under the control of the kernel to keep in sync, with a browser implementing at least three resident threads:JavaScript engine thread ,GUI render thread , browser Event trigger thread .
- The JavaScript engine is based on event-driven single-threaded execution, and the JavaScript engine waits for tasks in the task queue to be processed, and the browser will have only one JavaScript thread running the JavaScript program at any time.
- The GUI rendering thread is responsible for rendering the browser interface, which executes when the interface needs to be redrawn (Repaint) or when a return (Reflow) is caused by an operation. Note, however, that the GUI render thread is mutually exclusive to the JavaScript engine, and when the JavaScript engine executes the GUI thread is suspended, the GUI update is saved in a queue and executed immediately when the JavaScript engine is idle.
- An event triggers the thread that, when an event is triggered, adds the event to the end of the queue for processing by the JavaScript engine. These events can come from code blocks currently executing by the JavaScript engine, such as settimeout, other threads from the browser kernel such as mouse clicks, Ajax asynchronous requests, etc. But because of JavaScript's single-threaded relationship, all of these events are queued for JavaScript engine processing (asynchronous code executes only if no synchronization code is executed in the thread).
After understanding the mechanism of JavaScript single-threaded asynchronous execution, take a look at the specifics of settimeout () and SetInterval () at the time of execution.
SetTimeout () and SetInterval () SetTimeout ()
While executing settimeout (FN, 10), the JavaScript engine continues to execute the synchronization code behind settimeout (FN, 10) and, on the other hand, starts timing, inserting FN into the task queue after 10ms. After all synchronization code execution is complete (JavaScript engine is idle), the asynchronous code in the task queue is followed. Therefore, SetTimeout (FN, 10) does not perform exactly after 10ms, but is greater than or equal to 10ms.
Looking at the following two sections of code, you will have a more intuitive impression of the execution order of settimeout ().
First paragraph:
Console.log (1) setTimeout (function () {Console.log (' a ')}, SetTimeout (function () {console.log (' B ')}, 0), var sum = 0; for (var i = 0; i < 1000000; i + +) { sum + = i;} Console.log (sum); SetTimeout (function () {console.log (' C ');}, 0);
Output Result:
The logic of the code execution, the vertical representation of the time, the left side represents the execution order of the synchronous code, the task queue to the right that represents the async code, and the left-to-rear arrow indicates that the async code is inserted into the task queue
In the second paragraph, remove the for-loop upper limit by one 0:
Console.log (1) setTimeout (function () {Console.log (' a ')}, SetTimeout (function () {console.log (' B ')}, 0), var sum = 0; for (var i = 0; i < 100000; i + +) { sum + = i;} Console.log (sum); SetTimeout (function () {console.log (' C ');}, 0);
Output Result:
The difference between the two pieces of code is that the for loop executes at different times, the for loop execution time of the first code is greater than 10ms, so Console.log (' a ') is inserted into the task queue first, and Console.log (' C ') is inserted into the task queue after the for loop execution finishes. The For loop execution time of the second code is less than 10ms, so Console.log (' C ') is inserted into the task queue first.
SetInterval ()
SetInterval () is executed in a different way than settimeout (). If the execution of SetInterval (FN, 10), then every 10ms, the timer event will be triggered. As with settimeout (), if no synchronization code is currently executing (the JavaScript engine is idle), the method FN will be executed immediately, otherwise FN will be added to the task queue. Since the timer event is triggered every 10ms, it is possible to trigger an event, the last event of the processing method FN has not been able to get executed, still waiting in the queue, this time, this new timer event is discarded, continue to start the next time. It is important to note that because of this single-threaded asynchronous execution of the JavaScript engine, it is possible that the actual execution time interval of two FN is less than the set time interval. For example, the last Timer event processing method triggered, waiting for 5ms to get the opportunity to be executed. When the second timer event is triggered, it is executed immediately. So the time interval between the two is actually only 5ms. Therefore, setinterval () is not suitable for precise scheduling operations at fixed intervals.
The following code illustrates the problem:
Console.log (1) var interval = setinterval (function () { var date = new Date (); Console.log (date.getminutes () + ': ' + date.getseconds () + ': ' + date.getmilliseconds ());}, and var sum = 0;for (var i = 0; i < 1000000; i + +) { sum + = i;} Console.log (2);//Clear the timer, avoid the card dead browser settimeout (function () { clearinterval (interval);}, 100);
Output Result:
As can be seen, setinterval () two times before the interval is only 4ms. Since SetInterval () is triggered for the first time, the inside method is not executed immediately, but waits for the synchronization code to be executed before it is executed, which takes 6ms. So when the first method is executed after 4ms, the second method is also executed. The second time from SetInterval () is triggered, the subsequent executions are not blocked, so the interval is around 11ms.
In general, SetTimeout () and setinterval () do not meet the exact time interval. If the time interval is set at 10ms, FN in settimeout (FN, 10) may perform at an interval greater than 10ms, while FN in SetInterval (FN, 10) may perform less than 10ms.