This question already has answers here:
setInterval() behaviour with 0 milliseconds in JavaScript
(5 answers)
Closed 10 years ago.
setInterval()
Calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.
while()
Creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before
executing the statement.
If I use while(true) to execute a specific statement, my browser either crashes(Firefox), lags(Opera), or the statement won't be executed(Chrome), but if I used setInterval() with a fixed time of 0 seconds, everything works perfectly, even though its only 0 seconds, and while(true) can't logically be faster than 0 seconds, but why does this happen?
while() example:
<!DOCTYPE html>
<html>
<body>
<div id="counter"></div>
<script>
var i = 0;
while (true)
{
document.getElementById("counter").innerHTML += i++;
}
</script>
</body>
</html>
setInterval() example:
<!DOCTYPE html>
<html>
<body>
<div id="counter"></div>
<script>
var i = 0;
setInterval(function() { counter() }, 0);
function counter()
{
document.getElementById("counter").innerHTML += i++;
}
</script>
</body>
</html>
There is a large difference which involves locking. The first approach, the while loop is going to lock up the user's cpu because it runs forever without stopping and will take up 100% of the processor. setInterval actually has a minimum amount which is implicit, and depends on the browser. I believe it is around 10ms. So, your setInterval is actually only running for a millisecond or so doing that simple update, once every 10ms. This is harsh on the processor, but will not require 100% of the processor and can be mitigated with task management by the operating system.
while(1) generates an infinite loop, that is, JavaScript will simply run forever and never give control back to the browser, which therefor freezes, because it is unable to to anything else ever again (until the script is killed).
setTimeout(func, 0) behaves differently in the sense that after it executes, control is given back to the browser, which may then decide what to do after. Setting 0ms in setTimeout does not guarantee that the JavaScript code is run directly after it stops. With the 0ms parameter you merely tell the browser that you'd like the code to run directly after it stops, but the browser is free to do something else entirely before actually doing so.
Javascript in browsers is single threaded and event driven. No two things run concurrently, ever, and the event loop is king. If your JS never gives up control of the single thread (by ending a function), then nothing else can use the thread. The same thread handles JS and DOM, so the user can't even scroll or click on anything if your JS is hogging the thread.
setInterval (or indeed setTimeout) with a delay of 0 (milliseconds, not seconds) only means add this function to the event queue after the given delay, there is no guarantee the function will be executed at that exact time.
EDIT : actually, web workers can run JS at the same time as the main browser thread, but they don't see any of the same memory / can't access the DOM, so the points / assumptions above still hold, sort of... If you want to get into Web workers, you'll want a pretty good understanding of JS / functional programming.
EDIT (again) : Why do you want to loop forever? If you are polling (only reason I could think of), please don't do that. There's almost always a better way, especially in JS. The functional way, is to define the function you want executed when an event occurs (the thing you were polling for), and then attach that function to the event (how you do this depends on the event).
while(true) will block any execution until the conditional loop is finished, which we already know will never happen. (Chrome)
setInterval tells the environment to execute arbitrary code every x milliseconds, it wont block your browser because the "scheduler" has still the control.
Do you have a particular reason for using a never-ending loop, and even, manipulating the DOM with every each step?
If you use the while loop it'll most likely to lock the browser and client completely, also causing a possible CPU over-load if not terminated in a way.
The loop while tries to finish it's work in the most possible least microseconds. So it may even try to execute a million steps in a possible second, and maybe even more, in this case it depends on the client. However, at such speed updating the DOM wouldn't be possible.
In the case for setInterval, it's quite different from while loop, in fact, it's more appropriate to call it a function repeater. It repeats the given function after the given time is passed. So even if the time is 0, it has a step where it checks if the waiting time has passed now, and should the next repeat be run.
So you may consider while loop more instant than of 0 seconds delay.
Related
If the code is exactly the same every time it runs, why didn't it use exact same amount of execution time?
For example, code as simple as:
console.time();
console.timeEnd();
would yield different result every time I run it.
To understand why it is so, first of all you should know JS works in conurrency model. There is event loop in Javascript which is responsible for executing the JS code. So this reference will definitely help to answer this question.
There are lots of things happening that use memory in your computer while you have your browser open and your script is running. Those things affect how much memory your browser has access to. The more memory your browser has available at that time, the faster your script will run.
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.
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.
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.
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.