How does setTimeout work in Node.JS? - javascript

I guess that once it's executed it's on the queue, but in the queue is there any assurance it will invoke exactly after X milliseconds? Or will other heavy tasks higher on the queue delay it?

The semantics of setTimeout are roughly the same as in a web browser: the timeout arg is a minimum number of ms to wait before executing, not a guarantee. Furthermore, passing 0, a non-number, or a negative number, will cause it to wait a minimum number of ms. In Node, this is 1ms, but in browsers it can be as much as 50ms.
The reason for this is that there is no preemption of JavaScript by JavaScript. Consider this example:
setTimeout(function () {
console.log('boo')
}, 100)
var end = Date.now() + 5000
while (Date.now() < end) ;
console.log('imma let you finish but blocking the event loop is the best bug of all TIME')
The flow here is:
schedule the timeout for 100ms.
busywait for 5000ms.
return to the event loop. check for pending timers and execute.
If this was not the case, then you could have one bit of JavaScript "interrupt" another. We'd have to set up mutexes and semaphors and such, to prevent code like this from being extremely hard to reason about:
var a = 100;
setTimeout(function () {
a = 0;
}, 0);
var b = a; // 100 or 0?
The single-threadedness of Node's JavaScript execution makes it much simpler to work with than most other styles of concurrency. Of course, the trade-off is that it's possible for a badly-behaved part of the program to block the whole thing with an infinite loop.
Is this a better demon to battle than the complexity of preemption? That depends.

The idea of non-blocking is that the loop iterations are quick. So to iterate for each tick should take short enough a time that the setTimeout will be accurate to within reasonable precision (off by maybe <100 ms or so).
In theory though you're right. If I write an application and block the tick, then setTimeouts will be delayed. So to answer you're question, who can assure setTimeouts execute on time? You, by writing non-blocking code, can control the degree of accuracy up to almost any reasonable degree of accuracy.
As long as javascript is "single-threaded" in terms of code execution (excluding web-workers and the like), that will always happen. The single-threaded nature is a huge simplification in most cases, but requires the non-blocking idiom to be successful.
Try this code out either in your browser or in node, and you'll see that there is no guarantee of accuracy, on the contrary, the setTimeout will be very late:
var start = Date.now();
// expecting something close to 500
setTimeout(function(){ console.log(Date.now() - start); }, 500);
// fiddle with the number of iterations depending on how quick your machine is
for(var i=0; i<5000000; ++i){}
Unless the interpreter optimises the loop away (which it doesn't on chrome), you'll get something in the thousands. Remove the loop and you'll see it's 500 on the nose...

setTimeout is a kind of Thread, it holds a operation for a given time and execute.
setTimeout(function,time_in_mills);
in here the first argument should be a function type; as an example if you want to print your name after 3 seconds, your code should be something like below.
setTimeout(function(){console.log('your name')},3000);
Key point to remember is, what ever you want to do by using the setTimeout method, do it inside a function. If you want to call some other method by parsing some parameters, your code should look like below:
setTimeout(function(){yourOtherMethod(parameter);},3000);

The only way to ensure code is executed is to place your setTimeout logic in a different process.
Use the child process module to spawn a new node.js program that does your logic and pass data to that process through some kind of a stream (maybe tcp).
This way even if some long blocking code is running in your main process your child process has already started itself and placed a setTimeout in a new process and a new thread and will thus run when you expect it to.
Further complication are at a hardware level where you have more threads running then processes and thus context switching will cause (very minor) delays from your expected timing. This should be neglible and if it matters you need to seriously consider what your trying to do, why you need such accuracy and what kind of real time alternative hardware is available to do the job instead.
In general using child processes and running multiple node applications as separate processes together with a load balancer or shared data storage (like redis) is important for scaling your code.

setTimeout(callback,t) is used to run callback after at least t millisecond. The actual delay depends on many external factors like OS timer granularity and system load.
So, there is a possibility that it will be called slightly after the set time, but will never be called before.
A timer can't span more than 24.8 days.

Related

A better approach to request data from server every x minute

I know that I can use setInterval to send a request to server every 1 minute to see if something new added to the database so I can fetch it and update the UI according to this
but for what I've read from different article I got confused some say it's bad practice and other use it
SO I'm asking here to see if there's better approach to accomplish this or setInterval will handle the mission without any issues
Well If you had to know if something has changed I would think about using sockets is a better choice. Of course if your server is ready to implement this kind of mechanism.
If you don't have an opportunity to change logic on the server (third-party API or something) setTimeout on practice most common solutions.
But with this kind of solutions you have some caveats:
you should handle by yourself when to clear your timeout; if you don't then you'll have a memory leaks at least;
something would never change, big amount of data - this kind of optimizations you need to implement with caching strategies;
not sure about security - servers can block your app because of DDOS in the case when a lot of your users work with this service;
setTimeout by itself is ok. Depends on your situation if there is better or more appropriate solutions.
You may configure a simple cronjob.
Whether you use it from your VPS or shared hosting (most of them have cron installed), whether you may use a free online service like cron-job.org.
No problem with setInterval and setTimeout but don't forget JS is mono-thread and chosing the one that corresponds to our needs, given that the difference is important between them.
This interesting point not from me :
The setInterval thing is less of a performance tip but more of a
concurrency best practice. setInterval has the potential to execute
code prematurely to when you're expecting.
E.g.,
function doSomething () {
// I take 500 ms to run
}
doSomething();
setInterval(doSomething, 150);
This bit of code will run then next iteration doSomething immediately
after it's finished executing the current iteration. The interval
timer never stops! This has the potential to freeze your runtime
environment by continuously running its code and not allowing the
system to do other things.
function doSomething () {
// I take 500 ms to run
setTimeout(doSomething, 150);
}
doSomething();
Even though this looks essentially the same the difference is that
doSomething will always wait 150 ms after running before requeuing the
next iteration for execution. This allows the system to run other
operations and prevents your runtime from being locked up.
https://www.reddit.com/r/javascript/comments/51srsf/is_it_still_true_that_we_shouldnt_use_setinterval/

Performance of setTimeout in node?

For my webapp I'm going to need to have many timeouts running at once at any given point, possibly around 10,000-100,000. What I'm wondering is how well this function scales.
I don't need it to be that accurate, mostly accurate within 10-100 ms. Would it be better to have a single function run on an interval (say, to run every 50 ms), that checks the current datetime compared to the saved datetime and invokes the function if so?
Does anyone have any insight in to the underlying implement of setTimeout and can shed some light as to how well it can be used en-masse?
More questions I had: Does anyone know of a limit to how many timeouts can be running at once? Also, with both approaches I'm concerned about there not being enough time to process each timeout per interval and it getting "behind" in terms of triggering the timeout function in time.
Actually you cannot determine the exact interval between timeouts, because all it does is it pushes your callback to the callback queue after the threshold and when the event loop will get that callback, push to the call stack and execute it - is non-deterministic. The same is with intervals. You may appear in a situation, when, for example, 5 callbacks will be executed one after another without a delay. This is javascript ))
This is too long for a comment.
possibly around 10,000-100,000
Let's consider what this means. Say that each queued callback takes ~10ms to run, and you queue up 50,000 of them to run in 50ms. Only one of them can run at a time. So by the time the event loop even checks to see if it's time to run the 1000th callback, 10 whole seconds have passed. By the time you get to the 50,000th callback it will have been ten whole minutes! Now obviously if your queued callbacks take fractions of a millisecond that two order-of-magnitude dropoff makes the math a little less dismal, but if they have to do any I/O this probably isn't going to work and it probably won't work no matter what, at least not for a webapp that also has to serve clients.

Is it possible to have "setInterval" set too fast?

I have a setinterval function in my javascript that I want to be as fast as possible, i.e. check the status of an event every 1ms. Is it possible that this would be asking too much from a user's browser? It seems to work just fine, but I am wondering if its a bad practice.
It is not only possible, it's quite common. It's a race-condition by its very nature. If you depend on the code inside the callback to be executed before the next interval, use a recursive setTimeout instead.
Also, unless your interval is called lockUpBrowser, that duration between callbacks is likely much too short for realistic performance handling.
(function myRecursiveTask() {
// Do your task here
myTask();
if (!someConditionToAllowABailOut) {
setTimeout(myRecursiveTask, 100); // 100ms loop
}
}());
setInterval is not guaranteed to execute at precisely the interval specified.
It will execute as soon as possible, but since javasript is single-threaded and some other code may execute at this time your callback may be delayed.
If you're using setInterval with 1ms than you're probably trying to solve your problem in a wrong way.
Yes, if the function reference passed to setInterval takes longer to execute than the interval, calls to the function will queue and bog down the browser. If you're trying to perform an animation and want to change each step as fast as possible, there is a requestAnimationFrame function that should be used for modern browsers. Personally, I've never needed to perform a function faster than every 15ms.
I would certainly question the need for such an approach. What are you needing to check for every 1ms that you can't check for every 10ms, 100ms, or every second?
Are you 100% certain that the check functionality that you will run every will always execute in < 1ms such that you don't have multiple check processes stacking up to run.
How much memory and CPU does the process take, and are you going to potentially slow down the user's browser to the point where simply actions like scrolling become painful for the user?
is an while loop too slow for you?
while (condition)
{
//code block to be executed
}
i know i'm not ansering your question but, i think there is no better ways to do something like that...
Ben Cherry has a good article about this where he tests different browsers to find how fast setInterval can be before it becomes unreliable. The speed at which a setInterval or setTimout fires is dependent on the browser.
In particular, if you’re looking for consistent timer intervals across browsers, you have to use something >15ms.
So if you can set the time greater than 15ms you won't run into problems.

JavaScript execution hangs page momentarily

I have a web application which uses jQuery/JavaScript heavily. It holds a large array in memory, and the user filters it by typing in a textbox.
Problem: When the filtering algorithm runs, the application becomes non-responsive and the browser may even ask the user whether to let the script continue.
Optimally, I would like the filter function to run in a separate thread, to avoid non-responsiveness. Is this possible in any way? Alternatively, I would like to show a rotating hourglass or similar, but browsers seem unable to display animated GIFs when running heavy scripts.
What is the best way of attacking the problem?
Browsers execute scripts in the main event processing thread. This means any long running scripts can holdup the browser queue.
You should split your filter logic into chunks and run them on timeout callback's. You may use a gap of 0 mills between executions. 0 milli's is just a suggestion to the browser, but the browser will use the gap between subsequent callbacks to clear its event queue. Timeout's is generally how long running scripts are ought to be executed in the browser environment to prevent the page from "hanging".
This type of job is what Web Workers were designed for, support is patchy, but improving.
Expanding on my comment from earlier, given that you are processing an array you are probably using a for loop. You can easily refactor a simple for loop to use setTimeout() so that the work is broken up into chunks and the browser gets a chance to handle screen paints and user interaction between each chunk. Simple example:
// Generic function to execute a callback a given number
// of times with a given delay between each execution
function timeoutLoop(fn, startIndex, endIndex, delay) {
function doIteration() {
if (startIndex < endIndex){
fn(startIndex++);
setTimeout(doIteration, delay);
}
}
doIteration();
}
// pass your function as callback
timeoutLoop(function(i) {
// current iteration processing here, use i if needed;
}, 0, 100, 0);
Demo: http://jsfiddle.net/nnnnnn/LeZxM/1/
That's just something I cobbled together to show the general idea, but obviously it can be expanded in various ways, e.g., you might like to add a chunkSize parameter to timeoutLoop() to say how many loop iterations to do in each timeout (adding a conventional loop around the call to fn()), etc.

Call setTimeout without delay

Quite often see in JavaScript libraries code like this:
setTimeout(function() {
...
}, 0);
I would like to know why use such a wrapper code.
Very simplified:
Browsers are single threaded and this single thread (The UI thread) is shared between the rendering engine and the js engine.
If the thing you want to do takes alot of time (we talking cycles here but still) it could halt (paus) the rendering (flow and paint).
In browsers there also exists "The bucket" where all events are first put in wait for the UI thread to be done with whatever it´s doing. As soon as the thread is done it looks in the bucket and picks the task first in line.
Using setTimeout you create a new task in the bucket after the delay and let the thread deal with it as soon as it´s available for more work.
A story:
After 0 ms delay create a new task of the function
and put it in the bucket. At that exact moment the UI thread is busy
doing something else, and there is another tasks in the bucket
already. After 6ms the thread is available and gets the task infront
of yours, good, you´re next. But what? That was one huge thing! It has
been like foreeeeeever (30ms)!!
At last, now the thread is done with that and comes and gets your
task.
Most browsers have a minimum delay that is more then 0 so putting 0 as delay means: Put this task in the basket ASAP. But telling the UA to put it in the bucket ASAP is no guarantee it will execute at that moment. The bucket is like the post office, it could be that there is a long queue of other tasks. Post offices are also single threaded with only one person helping all the task... sorry customers with their tasks. Your task has to get in the line as everyone else.
If the browser doesn´t implement its own ticker, it uses the tick cycles of the OS. Older browsers had minimum delays between 10-15ms. HTML5 specifies that if delay is less then 4ms the UA should increase it to 4ms. This is said to be consistent across browsers released in 2010 and onward.
See How JavaScript Timers Work by John Resig for more detail.
Edit: Also see What the heck is the event loop anyway? by Philip Roberts from JSConf EU 2014. This is mandatory viewing for all people touching front-end code.
There are a couple of reasons why you would do this
There is an action you don't want to run immediately but do want to run at some near future time period.
You want to allow other previously registered handlers from a setTimeout or setInterval to run
When you want to execute rest of your code without waiting previous one to finish you need to add it in anonymous method passed to setTimeout function. Otherwise your code will wait until previous is done
Example:
function callMe()
{
for(var i = 0; i < 100000; i++)
{
document.title = i;
}
}
var x = 10;
setTimeout(callMe, 0);
var el = document.getElementById('test-id');
el.innerHTML = 'Im done before callMe method';
That is the reason I use it.
Apart from previous answers I'd like to add another useful scenario I can think of: to "escape" from a try-catch block. A setTimeout-delay from within a try-catch block will be executed outside the block and any exception will propagate in the global scope instead.
Perhaps best example scenario: In today's JavaScript, with the more common use of so called Deferreds/Promises for asynchronous callbacks you are (often) actually running inside a try-catch.
Deferreds/Promises wrap the callback in a try-catch to be able to detect and propagate an exception as an error in the async-chain. This is all good for functions that need to be in the chain, but sooner or later you're "done" (i.e fetched all your ajax) and want to run plain non-async code where you Don't want exceptions to be "hidden" anymore.
AFAIK Dojo, Kris Kowal's Q, MochiKit and Google Closure lib use try-catch wrapping (Not jQuery though).
(On couple of odd occasions I've also used the technique to restart singleton-style code without causing recursion. I.e doing a teardown-restart in same loop).
To allow any previously set timeouts to execute.

Categories

Resources