Home > Article > Web Front-end > Detailed explanation of using timers to execute functions regularly in Node.js_node.js
If you are familiar with client-side JavaScript programming, you may have used the setTimeout and setInterval functions, which allow a delay in running a function for a period of time. For example, the following code, once loaded into the web page, will append "Hello there" to the page document after 1 second:
setTimeout(function() {
document.write('
Hello there.
');}, oneSecond);
And setInterval allows the function to be executed repeatedly at specified intervals. If the following code is injected into a Web page, it will cause "Hello there" to be appended to the page document every second:
setInterval(function() {
document.write('
Hello there.
'); }, oneSecond);
Because the Web has long become a platform for building applications, rather than simple static pages, this kind of similar demand is increasingly emerging. These task scheduling functions help developers implement periodic form validation, delayed remote data synchronization, or UI interactions that require delayed responses. Node also fully implements these methods. On the server side, you can use them to repeat or delay many tasks, such as cache expiration, connection pool cleanup, session expiration, polling, etc.
Use setTimeout delay function to execute
setTimeout can formulate an execution plan to run the specified function once in the future, such as:
var timeout = setTimeout(function() {
console.log("timed out!");
}, timeout_ms);
Exactly the same as client-side JavaScript, setTimeout accepts two parameters. The first parameter is the function that needs to be delayed, and the second parameter is the delay time (in milliseconds).
setTimeout returns a timeout handle, which is an internal object. You can use it as a parameter to call clearTimeout to cancel the timer. Otherwise, this handle has no effect.
Use clearTimeout to cancel the execution plan
Once you obtain the timeout handle, you can use clearTimeout to cancel the function execution plan, like this:
var timeout = setTimeout(function() {
console.log("timed out!");
}, timeoutTime);
clearTimeout(timeout);
In this example, the timer will never be triggered, nor will the words "time out!" be output. You can also cancel the execution plan at any time in the future, as in the following example:
Make and cancel repeated execution plans for functions
setInterval is similar to setTimeout, but it will execute a function repeatedly at specified intervals. You can use it to periodically trigger a program to complete tasks such as cleaning, collection, logging, data acquisition, polling, etc. that need to be performed repeatedly.The following code will output a "tick" to the console every second:
console.log("tick");
}, period);
setInterval returns an execution plan handle, which can be used as a parameter of clearInterval to cancel the execution plan:
}, 1000);
// …
clearInterval(interval);
Use process.nextTick to delay function execution until the next round of the event loop
Sometimes client-side JavaScript programmers use setTimeout(callback,0) to delay the task for a short period of time. The second parameter is 0 milliseconds, which tells the JavaScript runtime to wait immediately after all pending events have been processed. Execute this callback function. Sometimes this technique is used to delay the execution of operations that do not need to be performed immediately. For example, sometimes you need to start playing animation or do some other calculations after the user event is processed.
In Node, just like the literal meaning of "event loop", the event loop runs in a loop that processes the event queue. Each round of the event loop's work process is called a tick.
You can call the callback function once every time the event loop starts the next round (next tick) of execution. This is exactly the principle of process.nextTick, and setTimeout and setTimeout use the execution queue inside the JavaScript runtime, and Not using event loop.
By using process.nextTick(callback) instead of setTimeout(callback, 0), your callback function will be executed immediately after the event in the queue is processed, which is much faster than JavaScript's timeout queue (in CPU time to measure).
You can delay the function until the next round of the event loop as follows:
my_expensive_computation_function();
});
Note: The process object is one of the few global objects in Node.
Blocking the event loop
The runtime of Node and JavaScript uses a single-threaded event loop. Each time it loops, the runtime processes the next event in the queue by calling the relevant callback function. When the event is executed, the event loop obtains the execution result and processes the next event, and so on until the event queue is empty. If one of the callback functions takes a long time to run, the event loop will not be able to handle other pending events during that time, which can make the application or service very slow.
When processing events, if memory-sensitive or processor-sensitive functions are used, the event loop will become slow, and a large number of events will accumulate, which cannot be processed in time, or even block the queue.
Look at the following example of blocking the event loop:
var a = 0;
while(true) {
a ;
}
});process.nextTick(function nextTick2() {
console.log("next tick");
});
setTimeout(function timeout() {
console.log("timeout");
}, 1000);
When using setTimeout, the callback functions will be added to the execution plan queue, and in this example they will not even be added to the queue. This is an extreme example, but you can see that running a processor-intensive task can block or slow down the event loop.
Exit the event loop
Using process.nextTick, you can postpone a non-critical task to the next round (tick) of the event loop, which releases the event loop so that it can continue to execute other pending events.Look at the example below. If you plan to delete a temporary file, but don’t want the callback function of the data event to wait for this IO operation, you can delay it like this:
process.nextTick(function() {
fs.unlink("/path/to/file");
});
Suppose you plan to design a function called my_async_function, which can perform certain I/O operations (such as parsing log files), and intend to let it execute periodically. You can use setInterval to implement it like this:
setInterval(function() {
my_async_function(function() {
console.log('my_async_function finished!');
},interval);//Translator’s Note: The previous “,interval” was added by me, the author may have omitted it due to a typographical error
Translator’s Note: (The bolded parts below are added by the translator and are not the content of the original book)
In order to facilitate the understanding of this part of the content, you can modify the author's code so that it can actually run:
(function my_async_function(){
setTimeout(function(){
console.log("1");
},5000);
},interval);
Run this code and take a look. You will find that after waiting for 5 seconds, "hello" is output every 1 second. Our expectation is that after the current my_async_function is executed (it takes 5 seconds), wait for 1 second before executing the next my_async_function. There should be an interval of 6 seconds between each output. This result is caused by the fact that my_async_function is not executed serially, but multiple ones are running at the same time.