This article starts in Alloyteam Team blog, link address http://www.alloyteam.com/2015/10/ turning-to-javascript-series-from-settimeout-said-the-event-loop-model/
As a developer who goes from other programming languages (C#/java) to JavaScript, SetTimeout () is a less well understood part of the process of learning JavaScript, and this article attempts to combine the implementations of other programming languages, From SetTimeout, the event cycle model
1. Speaking from settimeout
The SetTimeout () method is not the content defined by the ECMAScript specification, but rather belongs to the functionality provided by the BOM. View W3school definition of the SetTimeout () method, which is used to call a function or evaluate an expression after a specified number of milliseconds.
Syntax settimeout (fn,millisec), where FN represents the code to execute, either a string containing JavaScript code or a function. The second parameter, Millisec, is the time in milliseconds, which indicates how long the FN needs to be deferred for execution.
After calling the SetTimeout () method, the method returns a number that is the unique identifier of the plan execution code that can be used to cancel the timeout call.
At first my use of setTimeout () was relatively simple, and there was no deep understanding of its operating mechanism until I saw the following code
var New date;settimeout (function() {varnew date;console.log (' time Elapsed: ', End-start, ' Ms '; while (new Date-start < 1000) {};
In my initial knowledge of settimeout (), the delay is set to 500ms, so the output should be time elapsed:500 Ms. Because in an intuitive understanding, the JavaScript execution engine, in the execution of the above code, should be a sequence of execution from the top down, the settimeout function is executed before the while statement. In practice, however, the output is at least 1000ms delayed after the code has been run several times.
2.Java Implementation of the settimeout
Lenovo's previous experience of learning Java, the above JavaScript settimeout () confused me. Java implementation of the settimeout has a variety of API implementations, here we take the Java.util.Timer package as an example. Using the timer to implement the above logic in Java, run multiple times, the output is time elapsed:501 Ms.
Importjava.util.Date;ImportJava.util.Timer;ImportJava.util.TimerTask; Public classTimertest { Public Static voidMain (string[] args) {//TODO auto-generated Method Stub LongStart =System.currenttimemillis (); Timer Timer=NewTimer (); Timer.schedule (NewMyTask (start), 500); while(System.currenttimemillis ()-Start < 1000) {}; }}classMyTaskextendsTimerTask {Private LongT; PublicMyTask (Longstart) { //TODO auto-generated Constructor stubt=start; } @Override Public voidrun () {//TODO auto-generated Method Stub LongEnd =System.currenttimemillis (); System.out.println ("Time Elapsed:" + (End- This. T) + "MS"); } }
Here settimeout () Why this difference before the first talk about the implementation of Java.util.Timer principle.
The above code several key elements for the timer, the TimerTask class and the Timer class schedule method, through reads the related source code, may understand its realization.
Timer: A scheduling class for task tasks, like the TimerTask task, is an API class for the user to schedule the execution of a task through the schedule method. This class completes scheduling of tasks through the Taskqueue task queue and the TimerThread class.
TimerTask: Implements the Runnable interface, indicating that each task is a separate thread that provides the user with a custom task through the run () method.
TimerThread: Inherited from Thread, is the class that actually executes the task.
Taskqueue: A data structure that stores task tasks, implemented internally by a minimal heap, each member of the heap is timetask, and each task relies on TimerTask's Nextexecutiontime attribute values to sort Nextexecutiontime the smallest task at the front of the queue, enabling the earliest execution of reality.
According to the above source analysis can be summed up as shown in the flowchart, in fact, this is a multi-producer, single consumer producer-consumer model. The disadvantage of this approach is that when a task executes longer, it exceeds the time that the next task in Taskqueue starts executing, affecting the real-time performance of the entire task. In order to improve the real-time, we can use multiple consumers to spend together to improve processing efficiency and avoid such problems.
3. Find out the reasons for the results
Having seen Java.util.Timer's implementation of similar settimeout (), go back to the settimeout () method of the previous JavaScript and see why the previous output does not match expectations.
var start = new Date;settimeout ( function () { Span style= "color: #0000ff;" >var end = new Date;console.log ( ' Time elapsed: ', End-start, ' Ms ' 500 while (new Date-start < 1000) {};
By reading the code it is not difficult to see that the SetTimeout () method executes in the while () loop before it declares "want" to execute an anonymous function after 500ms, which is the registration of the anonymous function, which takes effect immediately after the SetTimeout () method executes. the while loop of the last line of code continues to run 1000ms, The delay time of the output of anonymous functions registered through the settimeout () method is always greater than 1000ms . describes the actual invocation of this anonymous function blocked by the while () loop, the actual call does not actually execute until the while () loop block has ended.
In Java.util.Timer, the solution to a timed task is accomplished through multithreading, where the Task object is stored in the task queue, and the task is executed in the new sub-thread by a dedicated scheduling thread. When registering an asynchronous task with the schedule () method, the dispatch thread starts working immediately on the child thread, and the main thread does not block the task from running.
This is one of the big differences between JavaScript and java/c#, the single-threaded mechanism of JavaScript. In an existing browser environment, the JavaScript execution engine is single-threaded, the main thread of the statements and methods, will block the running of the scheduled task, the execution engine only after the execution of the main thread of the statement, the timing of the task will actually execute, the period of time, may be greater than the time delay set when registering the task. At this point, JavaScript is very different from the java/c# mechanism.
4. Event Loop Model
In a single-threaded JavaScript engine, how does setTimeout () work, and here's a reference to the event loop model in the browser kernel. To put it simply, there is a task queue outside of the JavaScript execution engine, and when the SetTimeout () method is called in code, the deferred method of registration is referred to the other modules of the browser kernel (in the case of WebKit, which is the WebCore module), and when the delay method reaches the trigger condition, This delay method is added to the task queue when the delay time of the setting is reached. This process is handled by other modules in the browser kernel, independent of the main thread of the execution engine, which executes when the main thread method executes, and when it reaches an idle state, it is executed sequentially from the task queue, a process that is constantly circulating, called the event loop model.
Refer to the information in a speech, the above event cycle model can be described.
The heap (heap) and stack (stack) are generated when the main thread of the JavaScript execution engine runs. The code in the program goes into the stack to wait for execution, when the settimeout () method is called, that is, the right Webapis method in the diagram, the corresponding module of the browser kernel begins the processing of the delay method, when the delay method reaches the trigger condition, the method is added to the task queue for the callback. As long as the code in the execution engine stack finishes executing, the main thread reads the task queue and executes the callback function that satisfies the trigger condition in turn.
Take the example in the lecture to further illustrate
As an example of the code in the diagram, the execution engine starts executing the above code, which is equivalent to speaking of a main () method to join the execution stack. Continue to start Console.log (' Hi ') when the log (' Hi ') method into the stack, the Console.log method is a WebKit kernel support common method, rather than the previous figure Webapis involved in the method, so here log (' Hi ') The method immediately out of the stack is executed by the engine.
After the execution of the Console.log (' Hi ') statement is completed, the log () method is executed and the Hi is output. The engine continues down, adding settimeout (callback,5000) to the execution stack. The SetTimeout () method belongs to the Webapis method in the event loop model, and when the engine executes the SetTimeout () method out of the stack, the deferred function is given to the corresponding module, which is the timer module on the right of the graph.
The execution engine will settimeout out of the stack execution, the delay processing method to the WebKit Timer module processing, and then immediately continue to process the following code, then log (' SJS ') into the execution stack, then log (' SJS ') out of the stack execution, output SJS. When the execution engine executes the console.log (' SJS '), the program finishes processing, and the main () method is also stacked.
At this time after the SetTimeout method executes 5 seconds, the Timer module detects that the delay processing method reaches the trigger condition, so the delay processing method is added to the task queue. The execution engine's execution stack is empty at this point, so the engine starts polling to check if a task queue has a task to be executed, and then checks the delay method that has reached the execution condition, and then joins the execution stack with the delay method. The engine found that the delay method called the log () method, and then the log () method into the stack. Then execute the stack sequentially, output there, and empty the execution stack.
After emptying the execution stack, the execution engine will continue to poll the task queue to see if there are any tasks to execute.
the implementation of timer in 5.webkit
It is now possible to thoroughly understand the following code execution process, the execution engine first settimeout () method into the stack is executed, the execution of the delay method to the kernel corresponding module processing. The engine continues to process the following code, while the while statement blocks the engine for 1 seconds, while in this process the kernel Timer module has added the delay method to the task queue at 0.5 seconds, and after the engine execution stack is emptied, the engine takes the delay method into the stack and processes it, and the final output time exceeds the expected set time.
var New date;settimeout (function() {varnew date;console.log (' time Elapsed: ', End-start, ' Ms '; while (new Date-start < 1000) {};
The Webapis section mentioned in the previous event Loop Model diagram mentions DOM events, Ajax calls, and SetTimeout methods, which simply summarize them as webapis, and they also add callback functions to the task queue waiting for the engine to execute. This is a simplified description, in fact, the browser kernel to DOM events, Ajax calls and SetTimeout methods have corresponding modules to handle, WebKit kernel in the Javasctipt execution engine, there is an important module is WebCore module, HTML parsing, The calculation of CSS style is implemented by WebCore. For the three kinds of api,webcore mentioned in the diagram, Webapis provides the DOM Binding, network, timer module to handle the underlying implementation, here or continue to settimeout as an example, to see the implementation of the timer module.
The timer class is a necessary basic component of the WebKit kernel, which can be fully understood by reading the source code, and this article simplifies and analyzes its execution process.
The delay method registered by the SetTimeout () method is passed to the WebCore component timer module for processing. The key class in the timer is the Theadtimers class, which contains two important members, TIMERHEAP task queue and Sharedtimer method scheduling class. The delay method is encapsulated as a timer object, stored in the timerheap. Like the Java.util.Timer task queue, Timerheap also uses the smallest heap of data structures to sort nextfiretime as a keyword. Sharedtimer as the Timerheap scheduling class, when the timer object reaches the trigger condition, the delay method is added to the task queue mentioned in the event loop model through the interface associated with the browser platform.
Timerheap uses the smallest heap data structure, the task that expects the least delay time is executed first, and the expected delay time is the same two tasks, the order of execution is executed according to the order of registration .
varStart =NewDate;settimeout (function() {Console.log (' Fn1 ');}, 20); SetTimeout (function() {Console.log (' Fn2 ');}, 30); SetTimeout (function() {Console.log (' Another fn2 ');}, 30); SetTimeout (function() {Console.log (' Fn3 ');}, 10); Console.log (' Start while '); while(NewDate-start < 1000) {};console.log (' End While ');
The above code output is sequentially
while whilefn3fn1fn2another fn2
Resources
1. "JavaScript Asynchronous Programming"
2.JavaScript operation Mechanism: Another talk about event loophttp://www.ruanyifeng.com/blog/2014/10/event-loop.html
3.Philip roberts:help, I ' m stuck in an event-loop.https://vimeo.com/96425312
4.How JavaScript Timers work.http://ejohn.org/blog/how-javascript-timers-work/
5.How WebKit ' s event model Works.http://brrian.tumblr.com/post/13951629341/how-webkits-event-model-works
6.Timer implementation. http://blog.csdn.net/shunzi__1984/article/details/6193023
Turn to JavaScript series from settimeout say event loop model