This article to share is node.js in the timer of the relevant information, very comprehensive and meticulous, there is a need for small partners can refer to.
Realization of Timer in Node.js
The previous blog post mentions that the timer in node is not implemented by a new thread, but is done directly in the event loop. The following is a few examples of JavaScript timer and node-related source to analyze the timer function in the node in the end how to achieve.
Features of timer functions in JavaScript
Both the settimeout and SetInterval timer functions are available in both node and browser, and their working characteristics are essentially the same, so the following is an example of node.
We know that the timer in JavaScript is different from a timed interrupt at the bottom of the computer. When the interrupt arrives, the current execution code is interrupted to perform a timed interrupt handler function. And when the JavaScript timer comes in, if the current execution thread has no code executing, the corresponding callback function is executed; If the current code is in execution, the JavaScript engine neither interrupts the current code to perform the callback, nor does it open a new thread execution callback. Instead, the current code is completed before it is processed.
?
| 1 2 3 4 5 6 |
Console.time (' a ') settimeout (function () {console.timeend (' a ');}, 100); var i = 0; for (; i < 100000; i++) {} |
Execute the above code, you can see the final output time is not about 100ms, but a few seconds. This means that before the loop completes, the timer callback function is not actually executed, but is deferred to the end of the loop. Virtually all events are not processed in JavaScript code execution and must wait until the current code is complete to handle new events. That's why browsers lose their response when running time-consuming JavaScript code in a browser. In order to deal with this situation, we can take the yielding processes skill, divides the time-consuming code into the small block (chunks), executes once each piece to carry on the settimeout, the stipulation after a short period of time only then handles the next piece, but in this idle time, the browser/ Node can handle the events in the queue.
Supplementary information
Advanced timer and yielding processes are discussed in detail in advanced techniques in the 22nd chapter of JavaScript Advanced programming.
Timer implementation in node
LIBUV initialization of the uv_loop_t type
The previous blog post mentions that node will invoke LIBUV's Uv_run function to initiate default_loop_ptr for event scheduling, Default_loop_ptr point to a uv_loop_t type variable default_loop_struct. Node starts by calling Uv_loop_init (&default_loop_struct) to initialize it, and the Uv_loop_init function excerpt is as follows:
?
| 1 2 3 4 5 6 |
int Uv_loop_init (uv_loop_t* loop) {... loop->time = 0; Uv_update_time (loop); |
You can see that the time field of the loop is assigned a value of 0, and then the Uv_update_time function is called, which assigns the most recent count times to Loop.time.
After initialization is complete, Default_loop_struct.time has an initial value, and time-related operations are compared to this value to determine whether the corresponding callback function is invoked.
LIBUV's Event scheduling core
As mentioned earlier, the Uv_run function is the central part of the LIBUV library implementation event loop, and the following is its flowchart:
Here's a brief description of the timer-related logic above:
Updates the current loop's Time field, which marks "now" under the current loop concept;
Check to see if the loop is alive, that is, check if there are any tasks in the loop that need to be handled (handlers/requests);
Check the registered timer, if the time specified in a timer falls behind the current time, indicating that the timer has arrived, then executes its corresponding callback function;
Performs an I/O polling (that is, blocking the thread, waiting for an I/O event to occur), stopping waiting and executing the next timer's callback if the next timer expires without any I/O completion.
If an I/O event occurs, the corresponding callback is performed, and the timer is checked again and the callback is executed because the timer may expire during the execution of the callback.
(actually (4.) This is more complicated than just one step, so the description is focused on the implementation of the timer just to not involve other details. )
Node will always call Uv_run until the loop is no longer alive.
The Timer_wrap and timers in node
Node has a Timerwrap class that is registered as a timer_wrap module within the node.
Node_module_context_aware_builtin (Timer_wrap, Node::timerwrap::initialize)
Where the Timerwrap class is basically a direct encapsulation of the uv_timer_t, Node_module_context_aware_builtin is the macro that NODE uses to register the built-in module.
After this step, JavaScript will be able to get the module to operate. The Src/lib/timers.js file encapsulates the functionality of the timer_wrap using JavaScript, and exports Exports.settimeout, Exports.setinterval, Exports.setimmediate and other functions.
Node startup and global initialization
The previous article mentions that node startup will load the execution Environment loadenvironment (ENV), a very important step in this function is to load src/node.js and execute, src/node.js will load the specified module and initialize global and process. Of course, functions such as settimeout are also bound to the global object by Src/node.js.
The above mentioned is the entire content of this article, I hope you can enjoy.