I need to execute multiple functions one after another in fixed time intervals, thus using setTimeout. I want to ensure that I understand how it executes. I have following logic:
setTimeout(function() {
//Execute first function
}, 200);
setTimeout(function() {
//Execute second function
}, 400);
setTimeout(function() {
//Execute third function
}, 600);
Does this mean that first function executes after 200ms, second one 200ms after the first, and the third one 200ms after the second and so on? Or do I need to change something.
Does this mean that first function execute after 200ms, second one 200ms after first and third one 200ms after second and so on?
Essentially, yes that's what it means. Bear in mind however that the specification only guarantees that the delay parameter is a minimum time that must be awaited, and browsers can and do throttle these calls sometimes - notably if the tab is not active:
Note: This API does not guarantee that timers will fire exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected.
and:
Optionally, wait a further user-agent defined length of time.
Note: This is intended to allow user agents to pad timeouts as needed to optimise the power usage of the device. For example, some processors have a low-power mode where the granularity of timers is reduced; on such platforms, user agents can slow timers down to fit this schedule instead of requiring the processor to use the more accurate mode with its associated higher power usage.
Also, if any of your functions take a noticeable amount of time to run, the delay between the end of one function finishing and the next starting may not be 200ms - it could be less.
Following James' answer, in order to guarantee this minimum delay, you should trigger the next setTimeout() inside the anonymous callback, each of them with the 200ms delay specified:
setTimeout(function() {
//Execute first function
setTimeout(function() {
//Execute second function
setTimeout(function() {
//Execute third function
}, 200);
}, 200);
}, 200);
This way you can be sure that the delay between each function will be at least 200ms
Related
Consider the two functions below, both async, one a brutal workload that takes a lot of time, and the other one a wait function that waits a precise number of seconds by setting a timeout.
async function Brutal_Workload()
{
for(var x = 0; x< 1000 * 1000 * 1000; x++)
{
}
}
async function Time_Wait(seconds)
{
var promise = new Promise((resolve, reject) =>
{
var msecs = Math.floor(seconds * 1000);
var timer =
setTimeout(
function()
{
clearTimeout(timer);
resolve();
},
msecs);
});
return promise;
}
Now, let's call the first function in a setInterval cycle
setInterval(
async function()
{
await Brutal_Workload();
console.log("BLIP");
}, 1000 / 30);
All as intended: despite the interval running at 30 calls per second, I only get 1 blip per second, because Brutal_Workload is choking it.
But when I use the other function...
setInterval(
async function()
{
await Time_Wait(1);
console.log("BLIP");
}, 1000 / 30);
I get 30 BLIPs per second.
The Time_Wait function, which works otherwise just fine outside of setInterval, doesn't seem to work here.
Any idea of what might cause this behavior?
Ok, rather than continue the back-and-forth in the comments, I'm just going to post this as an answer.
Javascript is both single-threaded and concurrent. I know you know this, but you don't seem to realize the implications. In your first function, you only see a console.log every so often, because your "brutal workload" blocks the only thread of execution until it completes, which means that regardless of what number you passed to setInterval not only is no other invocation running, the next bit of work isn't even being queued to run because your brutal workload is blocking the only thread of execution.
Understand, the runtime environment's setInterval runs on the same (only) thread as your code, the JS engine doesn't cheat and run your stuff in one thread and setInterval in another. So while brutal workload is doing its thing, setInterval itself, much less the function you passed to it, is not running at all. Using async and wrapping your brutal workload in a Promise makes essentially zero difference in terms of our discussion here, because brutal workload dominates.
So that explains the first example, so far so good. On to the second.
Unlike the first example, in the second there is no long-running chunk of code to tie up the thread of execution. So your callback to setInterval runs, dutifully registers a thing to run in a second, and yields control of the thread of execution, something that again the first example does not (and cannot do). Here the Promise and async/await actually does enable concurrency which it can't do in the first example because brutal workload is hogging the thread. So in a fraction of a second your callback to setInterval runs again, dutifully queues up another thing to run after a second has passed, and so on.
So after ~1 second that first queued up log happens, and then after a fraction of a second after that the second, and then so on. This doesn't happen in the first example because although you told setInterval to run 30x/sec brutal workload means that setInterval itself can't run to even queue your callback to be ran.
I tried to make a stopwatch in the console, but the message kept on clearing before I had time to read it.
I tried increasing how long the Timeout function would go, but for some reason, it didn't make a difference.
Can somebody help me with making the messages not clear so fast?
setTimeout(function() {
console.log("1");
}, 1000);
setTimeout(function() {
console.clear()
},1099);
setTimeout(function() {
console.log("2");
}, 2000);
setTimeout(function() {
console.clear()
}, 2099);
setTimeout(function() {
console.log("3");
}, 3000);
setTimeout(function() {
console.clear()
}, 3099);
second argument to settimeout represents time in milliseconds. 1000ms = 1seconds. consider this. Maybe you should increase the time it takes to run the console.clear(), base on your code it executes after 2 and 3 seconds.
#Mr.Buscuit, consider using the setInveral function,
let sec = 0;
setInterval(function () {
console.clear();
console.log(sec);
sec++;
}, 1000);
This log a new number to the log every second. Hope this helps.
1- first line of code you tell your browser to execute that function which print on console number "1"
2- second line you tell browser after 99ms (from beginning of timer) NOT 1099ms clear the console
Why 99ms? because All Timer API(Browser API) e.g (setTimeout, setInterval) works at same time, all of these functions that you do, they have a one(only one) timer, hence that means when timer reach at 1000ms, second setTimeout that you determined its timer with 1099ms reached at 1000ms as well (one timer), hence still 99ms remaining from 1099ms
Summary
Imagine there is one big timer is running for all functions, this means if we have 2 setTimeout with time we specified 1000ms (2 function with same time) this is not means after finish first function that need 1000ms, second starts setTimeout timer that will begin from scratch, hence need 1000ms again with total latency 2000ms, No, this is wrong, two functions will work together
very good resource for understand this concept : Async Concept
I have next code
setTimeout(function() {
setTimeout(function() {
console.log('foo');
}, 50);
}, 100);
setTimeout(function() {
setTimeout(function() {
console.log('baz');
}, 100);
}, 50);
The question was what's the output. But on running code I got different results on multiple runs - sometimes it's foo baz, sometime it's baz foo.
So there is two questions:
1) why I have different results?
2) Why sometimes I got baz foo ?
P.S. There is code snippet, but with code snippet I always get the same result
P.P.S. If it's environment specific - I use Chrome ( and FF ), but questions still actual
P.P.S. Possible answer was about usage console.log, but for
var a = [];
setTimeout(function() {
setTimeout(function() {
a.push('foo');
}, 50);
}, 100);
setTimeout(function() {
setTimeout(function() {
a.push('baz');
}, 100);
}, 50);
setTimeout(function() { console.log(a); }, 300);
it's still actual
The timeout specified is a minimum time that the browser should wait before executing the function, not a guaranteed time. If the browser is busy doing other things when the timer goes off, the function will be delayed.
So when you schedule the timer for 50 ms, it might not actually run until 53 ms later. Then it will set another timer for 100 ms after that, which is 153 ms after you started. Meanwhile, the timer that's set for 100 ms could run in 101 ms, and then set its second timer for 50 ms later, which is 151 ms after everything started. In this example, it will print foo bar.
Or you could get different delays, and the result would be bar foo.
If you need to perform actions in a specific sequence, you should run them sequentially in a single function, or call the second one from a callback of the first, or use promises in a specific order. Depending on precise millisecond timing with setTimeout is not reliable.
setTimeout doesn't schedule things after the EXACT time you specify - its a an approximation that is used by the javascript engine to schedule your functions as close as possible to the time you specify. In general, you shouldn't rely on timeouts to guarantee the order of execution. Assume that your timeouts can fall within a range of time, and don't expect the specified time to be the exact time that your functions will run.
Read here for more info.
Welcome to the world of asynchronous/event driven programming!
One of key things to understand about timers in javascript (and general purpose timing functions in nearly all languages) is that they are not designed to be precise to the tick. What occurs instead is that the program tells the operating system/js engine to "hey, send me a notification when at least this much time has elapsed." The operating system/js engine, however, may have hundreds, thousands, or even millions of tasks it needs to prioritize and execute, so it can't spend all of it's time just watching the clock waiting to fire off that notification. So, to save processing power, keeps all of these timing events in a queue, and only periodically checks to see how much time has gone by and if the events have expired.
In your particular case, you have an timeout event being created as a result of a timeout event being fired. So if the initial event is delayed slightly, that pushes back start time and thus the expiration of the second event. In your foo/baz example, if the initial foo timeout is delayed but the initial baz is not, then the baz callback will be added to the event queue before the foo callback is, and you get "baz foo".
Or sometimes baz will get delayed and foo won't, or sometimes neither will, or sometimes they both will. There's just too much going on under the hood (maybe not even related to your script/code/program) to be able to predict or rely on the exact execution order. That's the takeaway, and it's a good policy to live by for basically all of event driven programming.
I'm working with the new mapbox.js API, especially the event callback 'panned'. The callback is fired about 50-100 times when the user moves the map, which is way too much. What's the best way to get only the first and the last event (or only the last) out of this?
map.addCallback('panned', function(move) {
console.log('panned');
});
Use .setTimeout:
var timeout = null;
map.addCallback('panned', function (move) {
timeout && window.clearTimeout(timeout);
timeout = window.setTimeout(function () {
console.log('panned')
}, 100)
})
For the timeout time choose an appropriate time, which you have to find out by fiddling around with several values.
UnderscoreJS has a few useful functions.
Debounce might be best suited for you, based on what you describe: ... postpone its execution until after wait milliseconds have elapsed since the last time it was invoked
"Throttle" is also useful: "... will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with."
HTH
Is there any way to call a function periodically in JavaScript?
The setInterval() method, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. It returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval().
var intervalId = setInterval(function() {
alert("Interval reached every 5s")
}, 5000);
// You can clear a periodic function by uncommenting:
// clearInterval(intervalId);
See more # setInterval() # MDN Web Docs
Please note that setInterval() is often not the best solution for periodic execution - It really depends on what javascript you're actually calling periodically.
eg. If you use setInterval() with a period of 1000ms and in the periodic function you make an ajax call that occasionally takes 2 seconds to return you will be making another ajax call before the first response gets back. This is usually undesirable.
Many libraries have periodic methods that protect against the pitfalls of using setInterval naively such as the Prototype example given by Nelson.
To achieve more robust periodic execution with a function that has a jQuery ajax call in it, consider something like this:
function myPeriodicMethod() {
$.ajax({
url: ...,
success: function(data) {
...
},
complete: function() {
// schedule the next request *only* when the current one is complete:
setTimeout(myPeriodicMethod, 1000);
}
});
}
// schedule the first invocation:
setTimeout(myPeriodicMethod, 1000);
Another approach is to use setTimeout but track elapsed time in a variable and then set the timeout delay on each invocation dynamically to execute a function as close to the desired interval as possible but never faster than you can get responses back.
Everyone has a setTimeout/setInterval solution already. I think that it is important to note that you can pass functions to setInterval, not just strings. Its actually probably a little "safer" to pass real functions instead of strings that will be "evaled" to those functions.
// example 1
function test() {
alert('called');
}
var interval = setInterval(test, 10000);
Or:
// example 2
var counter = 0;
var interval = setInterval(function() { alert("#"+counter++); }, 5000);
Old question but..
I also needed a periodical task runner and wrote TaskTimer. This is also useful when you need to run multiple tasks on different intervals.
// Timer with 1000ms (1 second) base interval resolution.
const timer = new TaskTimer(1000);
// Add task(s) based on tick intervals.
timer.add({
id: 'job1', // unique id of the task
tickInterval: 5, // run every 5 ticks (5 x interval = 5000 ms)
totalRuns: 10, // run 10 times only. (set to 0 for unlimited times)
callback(task) {
// code to be executed on each run
console.log(task.id + ' task has run ' + task.currentRuns + ' times.');
}
});
// Start the timer
timer.start();
TaskTimer works both in browser and Node. See documentation for all features.
You will want to have a look at setInterval() and setTimeout().
Here is a decent tutorial article.
yes - take a look at setInterval and setTimeout for executing code at certain times. setInterval would be the one to use to execute code periodically.
See a demo and answer here for usage
Since you want the function to be executed periodically, use setInterval
function test() {
alert('called!');
}
var id = setInterval('test();', 10000); //call test every 10 seconds.
function stop() { // call this to stop your interval.
clearInterval(id);
}
The native way is indeed setInterval()/clearInterval(), but if you are already using the Prototype library you can take advantage of PeriodicalExecutor:
new PeriodicalUpdator(myEvent, seconds);
This prevents overlapping calls. From http://www.prototypejs.org/api/periodicalExecuter:
"it shields you against multiple parallel executions of the callback function, should it take longer than the given interval to execute (it maintains an internal “running” flag, which is shielded against exceptions in the callback function). This is especially useful if you use one to interact with the user at given intervals (e.g. use a prompt or confirm call): this will avoid multiple message boxes all waiting to be actioned."