I want to schedule events, that will fire and call my predefined callback
How can schedule in js / jquery:
one time event?
recurring event (to call my function every minute, or five minutes)?
You want setTimeout for a one time event and setInterval for a repeating event.
Both take two arguments: a function and an interval of time specified in milliseconds.
var delay_millis = 1500;
//will alert once, at least half a second after the call to setTimeout
var onceHandle = window.setTimeout(function() {
alert("Time has passed!");
}, delay_millis);
//will alert again and again
var repeatHandle = window.setInterval(function() {
alert("Am I annoying you yet?");
}, delay_millis);
Bonus: if you keep around the values returned by calling these functions, you can cancel the callback if you need to.
var shutUpShutUp = function() {
window.clearInterval(repeatHandle);
};
shutUpShutUp(); //now I can hear myself think.
jQuery has nothing to do with it. You need JavaScript timers: setTimeout() and setInterval()
A one-time event is just scheduled with a setTimeout call. An easy way for a recurring event is to simply call setTimeout in the function that you are setting the timeout on.
The easiest way to schedule events (at predefined intervals) is window.setTimeout.
For a one time event, you set the timeout once and let the timeout fire.
For recurring events, you set the timeout once and then reset the timeout in the method that gets called.
You can bind a function to an event that will be run only once by using .one() in jQuery...
http://api.jquery.com/one/
For the problem of a timing threshold for an event, declare your event like this:
var clickAvailable = true;
$('#element').click(function(e) {
if(!clickAvailable) {
clickAvailable = false;
//your code
setTimeout(function() {
clickAvailable = true;
}, 5*60*1000); // 5 minutes...
}
});
Related
I'm not 100% sure how setTimeout works in JavaScript. Say I have something like this:
$(document).ready(function() {
testTimeout();
});
function testTimeout() {
alert("testing timeout");
setTimeout(testTimeout, 5000);
}
This would display a popup window every 5 after the page is ready. What would happen if then I called testTimeout from a button click?
$("#button").click(function() {
testTimeout();
});
Would the button click call testTimeout and add another timeout every 5 seconds? Or, would the button click reset the timeout from when the button was pressed? The reason I am asking is because I would like to design something like this where I can pass a parameter to my timeout function. When the web page starts up, I have a default parameter. However, if I press a button, I would like my timeout function to be called right away and every 5 seconds after with my new parameter. But, I don't want the timeout function with the old parameter to continue repeating. How can I achieve this? Any help and understanding would be greatly appreciated.
This would display a popup window every 5 after the page is ready.
No it wouldn't, it would show an alert repeatedly with no delay and/or cause a "too much recursion" error, because setTimeout(testTimeout(), 5000) calls testTimeout and passes its return value into setTimeout, just like foo(bar()) calls bar and passes its return value into foo.
If you remove the ():
function testTimeout() {
alert("testing timeout");
setTimeout(testTimeout, 5000);
// here --------------^
}
Then it would do that.
What would happen if then I called testTimeout from a button click?
You'd end up with the function being called twice as often (more than once every 5 seconds), because every time you call it, it reschedules itself. A third time would make it more frequently still (three times/second), and so on.
If you want to avoid that, one option is to remember the timer handle and cancel any outstanding timed callback if you call the function before then:
var handle = 0;
function testTimeout() {
clearTimeout(handle); // Clears the timed call if we're being called beforehand
alert("testing timeout");
handle = setTimeout(testTimeout, 5000);
}
(I initialized handle with 0 because calling clearTimeout with a 0 is a no-op.)
Have you tried to asign variable to your setinterval;
var foo = setTimeout(testTimeout(), 5000);
and then when right event comes just destroy that variable.
clearInterval(foo);
And now you can asign it again...
In your case it would simply repeat endlessly, because you're executing the function instead of passing the reference. You should do it like this:
function testTimeout() {
alert("testing timeout)";
setTimeout(testTimeout, 5000);
}
Note the missing braces after testTimeout. This tells setTimeout to execute that function, instead of the result of that function, which is how your original code behaved.
" I would like my timeout function to be called right away and every 5 seconds after with my new parameter. But, I don't want the timeout function with the old parameter to continue repeating "
In order to achieve what you're trying to do you should remove the timeout:
var timeoutId;
function testTimeout() {
alert("testing timeout)";
clearTimeout(timeoutId );
timeoutId = setTimeout(testTimeout, 5000);
}
Notes:
You can stop the previous timeoutI from firing by catching the id returned from the setTimeout method and passing that to the clearTimeout method
Which way is correct and more efficient in using setInterval() and clearInterval()?
1.
something = setInterval(function() {
try {
...load something
clearInterval(something);
} catch (e) {
// error
}
}, 5000);
2.
something = setInterval(function() {
try {
...load something
} catch (e) {
// error
}
}, 5000);
setTimeout(something, 7000);
EDIT:
For #2, I meant setTimeout() instead of clearInterval().Has been changed.
I assume the interval you're passing into clearInterval is meant to be something.
Your second example will never fire your timer, because you clear the timer immediately after setting it. You're also passing an argument (7000) into clearInterval that won't get used (clearInterval only accepts one argument).
Your first example is right provided that you want to clear the repeated timer at the point where you're calling clearInterval from within the handler. Presumably that's in an if or similar, because if you want a one-off timed callback you'd use setTimeout, not setInterval.
EDIT:
For #2, I meant setTimeout() instead of clearInterval().Has been changed.
That completely changes the question. No, that's not correct. setInterval schedules the function to be called repeatedly on the interval you give it, you don't pass its return value into setTimeout.
If you need something to happen over and over again you use setInterval if you only need it to happen once use setTimeout (you can simulate setInterval by chaining multiple timeouts one after the other). Timeouts only happen once therefore you do no need to clear them. Also clearInterval does not take a time argument so the interval you set will be cleared before it ever executes since classic javascript is synchronous.
just to complete the answer, take many care with setInterval(). if your "...load something" take sometime more time to load than the time according (for a reason or another). it will just don't do it for this time and will wait the next call of setinterval.
I encourage to use setTimeout() as much as possible instead.
You can find find below the use cases that are, according to me, aswering to your questions:
For your case 1:
var something = setInterval(function() {
// Do stuff, and determine whether to stop or not
if (stopCondition) {
clearInterval(something);
}
}, 5000);
For your case 2:
var something = setInterval(function() {
// Do stuff
}, 5000);
// Pass a function to setTimeout
setTimeout(function() {
clearInterval(something);
}, 17000);
I have created a JavaScript version of the Little Man Computer based on the Java one at http://www.atkinson.yorku.ca/~sychen/research/LMC/LMCHome.html
I have it working in by stepping through each instruction. I have a function called stepCode() that does this.
What I want is a function that will run the program, pausing for a second between each step until the simulated program ends.
The code I have is this:
function runProgram()
{
var milliseconds = 1000;
var timeOut;
programRunning = true;
while(programRunning)
{
timeOut = setTimeOut(stepCode(), milliseconds);
}
}
This seems does not work. It still performs all the stepCode() calls one after the other very quickly. I want to pause between each stepCode() call.
I'm obviously doing something wrong. Any ideas?
You should use setInterval instead of setTimeout. Additionally, you need to reference the function, not call the function:
var timeOut; // global timeout variable to ensure both methods have access to it.
function runProgram() {
var milliseconds = 1000;
timeOut = setInterval(stepCode, milliseconds); // use setInterval instead of setTimeout
}
function stepCode {
// ... code processing here ...
// I assume you are setting programRunning to false at some point in this method.
// Instead of setting programRunning = false, you would do:
clearInterval(timeOut);
// Note, if you only have one timeout interval set, you can use clearInterval();
}
setInterval will cause the stepCode function to run every 'milliseconds' until you call clearInterval(timeOut);; setTimeout will only queue it up once. Anything that is queued via setTimeout will not execute until the current flow of code has been completed. As a result, programRunning will run and queue up several setTimeout executions. Once the programRunning variable hit false, the current code flow will finish and ALL of the queues will wait 1 second, and effectively execute all at the same time, or in rapid succession.
When you pass in a method call (e.g. stepCode()), it will call the method. You have to pass a reference to the function stepCode (notice no parens), to ensure that it knows what to run each time it executes.
This Fiddle Demo simulates a counter, which is common thing people attempt to execute using setInterval. It demonstrates the basic concept and use of setInterval.
In addition to suggested setInterval use that will call stepCode at 1 second intervals until cleared (or until the page is reloaded), and correction of removing () after stepCode that results in immediate stepCode executon, you can still use setTimeout if they are chained as shown below. Depending on what stepCode does and how long it takes, this solution has an advantage of ensuring that there is 1 second of idle time between the end of the previous and the beginning of the next stepCodes.
var milliseconds = 1000;
function runProgram()
{
programRunning = true;
stepCodeWrapper();
}
function stepCodeWrapper() {
if (programRunning) {
stepCode();
setTimeOut(stepCodeWrapper, milliseconds);
}
}
Just try with:
timeOut = setInterval(stepCode, milliseconds);
Bic, thanks for your swift response. You are correct about the programRunning flag being set to false inside the stepCode() function. I've set it as a global variable so that I could possibly halt the program by pressing a button, but thats another problem.
Tried both setInterval and setTimeout. You are right about it repeatedly calling the function. Using either method locks up the browser with repeated function calls. This is probably as its in a while loop. I cannot think of another was to repeatedly call the stepCode() function otherwise.
I sort of understand the difference between setInterval & setTimeout. Thanks, and I understand that would make the while loop redundant, but then how to stop it calling the stepCode function when the programRunning flag is set to false?
I have a flurry of interrupts coming into a handler and I don't want to service them until 5ms have passed since the last interrupt, indicating the flurry is over.
My thought was to call setTimeout(LookAtInterrupts, 5) each time the handler is entered, but I don't see in the setTimeout() documentation that it will cancel a pending scheduled call if it's called before that execution occurs.
Is that, in fact, what it will do? I don't want to get called 5ms after every handler interrupt, just the last one.
No, it won't - you can have as many pending timeouts as you want.
The function returns a key that you can use to cancel a timeout later:
var key = setTimeout( ... );
Then to cancel it later:
clearTimeout(key);
Calling clearTimeout() with an already-expired key is not an error, so you don't have to worry about synchronization problems.
setTimeout will not reset itself.
You can reset a timeout manually by
var timeout = setTimeout(...);
clearTimeout(timeout);
A setTimeout() won't cancel any previous timeouts implicitly.
However, you can achieve that by storing the identifier in a variable and clearing that each time.
var timeoutId = null;
var yourFn = function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(fn, 5);
};
You need to store a reference. setTimeout result can be stored and cleared later on.
For a "resettable" setTimeout:
// first assign it
var timeout = setTimeout(function(){
foo();
}, 50);
// then look for an existing assignment before re-assinging
if (timeout) clearTimeout(timeout);
timeout = setTimeout(function(){
bar();
}, 50);
References:
setTimeout
clearTimeout
As an aside, be careful when setting a timeout < 5ms. Though HTML5 is supposed to support 4, I doubt you're actually getting anywhere close to that (w/ cost of spinning up the timeout).
Store reference to that setTimeout call in a variable, and after each successfull interrupt, before creating timeout, cancel the previous timeout,
var tv = null;
function interrupt(){
if(tv !== null){
clearTimeout(tv);
}
tv = setTimeout(LookAtInterrupts,5)
}
function LookAtInterrupts(){
}
By this, you'll guarantee that only the last interrupt will continue execution in 5ms intervals. I hope that was clear.
While you can implement this yourself, a more practical solution would be to grab underscore.js and use it's debounce function (see http://underscorejs.org/#debounce).
Then you can do:
var lookAtInterrupts = _.debounce(handleInterrupt, 5);
the resulting function will only run at most once every 5 ms.
When setTimeout() is executed it schedules one call to your binded function().
If you want to cancel it you have to get ID returned by setTimeout() and clear as:
var timeOutID = setTimeout( LookAtInterrupts, 5 );
(...)
clearTimeOut( timeOutID );
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