Repeating setTimeout - javascript

I am trying to repeat setTimeout every 10 seconds. I know that setTimeout by default only waits and then performs an action one time. How can I repeat the process?
setTimeout(function() {
setTimeout(function() {
console.log("10 seconds");
}, 10000);
}, 10000);

Maybe you should use setInterval()

setInterval() is probably what you're looking for, but if you want to do get the same effect with setTimeout():
function doSomething() {
console.log("10 seconds");
setTimeout(doSomething, 10000);
}
setTimeout(doSomething, 10000);
Or if you don't want to declare a separate function and want to stick with a function expression you need to make it a named function expression:
setTimeout(function doSomething() {
console.log("10 seconds");
setTimeout(doSomething, 10000);
}, 10000);
(Or use arguments.callee if you don't mind using deprecated language features.)

according to me setInterval() is the best way in your case.
here is some code :
setInterval(function() {
//your code
}, 10000);
// you can change your delay by changing this value "10000".

Unlike the answers provided by #nnnnnn and #uzyn I discourage you from making use of setInterval for reasons elaborated in the following answer. Instead make use of the following Delta Timing script:
function DeltaTimer(render, interval) {
var timeout;
var lastTime;
this.start = start;
this.stop = stop;
function start() {
timeout = setTimeout(loop, 0);
lastTime = + new Date;
return lastTime;
}
function stop() {
clearTimeout(timeout);
return lastTime;
}
function loop() {
var thisTime = + new Date;
var deltaTime = thisTime - lastTime;
var delay = Math.max(interval - deltaTime, 0);
timeout = setTimeout(loop, delay);
lastTime = thisTime + delay;
render(thisTime);
}
}
The above script runs the given render function as close as possible to the specified interval, and to answer your question it makes use of setTimeout to repeat a process. In your case you may do something as follows:
var timer = new DeltaTimer(function (time) {
console.log("10 seconds");
}, 10000);
var start = timer.start();

const myFunction = () => {
setTimeout(() => {
document.getElementById('demo').innerHTML = Date();
myFunction();
}, 10000);
}
Easiest, but not efficient way!

Here is a function using setTimeout that tried to call itself as close as it can to a regular interval. If you watch the output, you can see the time drifting and being reset.
<script type="text/javascript">
function Timer(fn, interval) {
this.fn = fn;
this.interval = interval;
}
Timer.prototype.run = function() {
var timer = this;
var timeDiff = this.interval;
var now = new Date(); // Date.now is not supported by IE 8
var newInterval;
// Only run if all is good
if (typeof timer.interval != 'undefined' && timer.fn) {
// Don't do this on the first run
if (timer.lastTime) {
timeDiff = now - timer.lastTime;
}
timer.lastTime = now;
// Adjust the interval
newInterval = 2 * timer.interval - timeDiff;
// Do it
timer.fn();
// Call function again, setting its this correctly
timer.timeout = setTimeout(function(){timer.run()}, newInterval);
}
}
var t = new Timer(function() {
var d = new Date();
document.getElementById('msg').innerHTML = d + ' : ' + d.getMilliseconds();
}, 1000);
window.onload = function() {
t.run();
};
</script>
<span id="msg"></span>

Using jQuery, this is what you could do:
function updatePage() {
var interval = setTimeout(updatePage, 10000); // 10' Seconds
$('a[href]').click(function() {
$(this).data('clicked', true);
clearInterval(interval); // Clears Upon Clicking any href Link
console.log('Interval Cleared!');
});
// REPLACE 'YOUR_FUNCTION_NAME' function you would like to execute
setTimeout(YOUR_FUNCTION_NAME, 500);
} // Function updatePage close syntax
updatePage(); // call the function again.

Related

Defining single function to handle functionality of other functions

I need to define a single function that handles the functionality provided by setSlide, setMobile, and hide and just pass in the function to be called by SetTimeout when the delay has occurred. I'm not sure how to do this. Can someone please explain how to accomplish this? Thank you.
(function($) {
var currentTime = new Date().getTime() / 1000;
var setSlide = function (timeout) {
setTimeout(showSlide, timeout * 1000);
},
showSlide = function () {
$('.newsletter-popup').addClass('slide-left');
},
setMobile = function (timeout) {
setTimeout(showMobile, timeout * 1000);
},
hide = function (timeout) {
setTimeout(hideMobile, timeout * 1000);
},
showMobile = function () {
$('.newsletter-popup').removeClass('hidden');
},
hideMobile = function () {
$('.newsletter-popup').addClass('hidden');
};
$(document).ready(function() {
if (readCookie('nl_suppress')) {
$('.newsletter-popup').removeClass('slide-left');
} else if (!readCookie('nl_display')) {
setSlide(10);
} else if (currentTime - readCookie('nl_display') > 86400) {
showSlide();
} else {
setSlide(currentTime - (readCookie('nl_display') + 86400));
}
$('.nlForm').submit(function() {
createCookie('nl_suppress', new Date(), 30);
});
function checkCookie() {
var date = new Date();
date.setTime(date.getTime() + (86400000));
$('.newsletter-popup').removeClass('slide-left');
hide(1);
if(readCookie('nl_display')) {
// already been clicked once, hide it
createCookie('nl_suppress', new Date(), 180);
return;
}
// first time this is clicked, mark it
createCookie('nl_display', new Date().getTime() / 1000, 180);
setMobile(14);
setSlide(15);
};
$('.newsletter-close').on('click', checkCookie);
});
})(jQuery);
It sounds like you want to create a function that does the same thing as setTimeout, but the delay multiplied by 1000 so that it is in seconds.
It would look like this:
function setTimeoutSeconds(func, delay) {
setTimeout(func, delay * 1000);
}
Then instead of calling setSlide, setMobile, or hide, you call setTimeoutSeconds with the desired callback.
setTimeoutSeconds(hideMobile, 1);
setTimeoutSeconds(showMobile, 14);
setTimeoutSeconds(showSlide, 15);
If you still wanted to have the setSlide... etc functions, you could use a partially applied function:
function applyTimeout(func) {
return function(delay) {
setTimeout(func, delay * 1000);
}
}
And then create them like this:
var setSlide = applyTimeout(showSlide);
And then call them the same way:
setSlide(15);
It's really simple:
const callFunctionWithTimeout = (fn, timeout) => setTimeout(fn, timeout * 1000)
Then, for example instead of setSlide(10), you do:
callFunctionWithTimeout(showSlide, 10)

setInterval(): How to stop then start itself again?

In a if statement, I want the interval to clear itself and then call object function of itself again to restart the interval.
Is such thing possible?
I tried it this way, but I'm getting unexpected behavior. I can see that the log keeps on logging every 200ms. While it should have stopped since the interval was stopped and restarted and the condition wouldn't evaluate to true anymore.
DateTime.prototype = {
start: function () {
var self = this;
sendAjaxRequest(this.timeUrl, function () {
var previousTime = new Date().getTime();
this.tickIntervalId = setInterval(function tick() {
var currentTime = new Date().getTime();
if ((currentTime - previousTime) < 0) {
console.log('You changed your time backwards. Restarting.');
self.stop(); // <-- stopping itself
self.start(); // <-- call to same method its running from
return;
}
self.dateElement.innerHTML = new Date();
previousTime = currentTime;
return tick;
}(), 200);
});
},
stop: function () {
clearInterval(this.tickIntervalId);
this.tickIntervalId = null;
}
}
I think the scope is wrong for the setInterval call.
Try to change
this.tickIntervalId = setInterval(function tick() {
to use self
self.tickIntervalId = setInterval(function tick() {

Stopping a Javascript setInterval that is delayed by a setTimeout

I'm having issue with this jsfiddle snippet:
http://jsfiddle.net/y45jN/7/
var mainFunction = function() {
this.text;
this.repeater;
}
var repeatEvery = function(func, interval) {
var now = new Date();
var delay = interval - now % interval;
function start() {
var intervalID = setInterval(func, interval);
func(intervalID);
}
setTimeout(start, delay);
};
mainFunction.prototype.start = function(printText) {
this.text = printText;
var self = this;
var func = function(intervalID) {
if(intervalID){
this.repeater = intervalID;
}
document.getElementById('test').innerHTML += this.text + '<br/>';
};
repeatEvery(_.bind(func, this),1000);
}
mainFunction.prototype.stop = function() {
clearInterval(this.repeater);
}
var test = new mainFunction();
test.start('hello');
setTimeout(test.stop,10000);
My goal is to call the stop function and stop the Interval that has been set by the start function.
You need to do
setTimeout(function(){ test.stop()}, 10000)
or
setTimeout(test.stop.bind(test), 10000); //Bind method is not available in IE8 though
instead of
setTimeout(test.stop, 10000);
The reason for this is that Javascript loses track of the "this" when you pass a callback to a function.

jQuery reset setInterval timer

My Jquery:
function myTimer() {
var sec = 15
var timer = setInterval(function() {
$('#timer').text(sec--);
if (sec == -1) {
clearInterval(timer);
alert('done');
}
} , 1000);
}
$("#knap").click(function() {
myTimer();
});
$("#reset").click(function() {
// set timer to 15 sec again..
});
I want the timer to be reset when clicked on #reset.
You need to leave your "timer" variable in a scope that is available the next time you call the myTimer function so you can clear the existing interval and reset it with a new interval. Try:
var timer;
functionn myTimer() {
var sec = 15
clearInterval(timer);
timer = setInterval(function() {
$('#timer').text(sec--);
if (sec == -1) {
clearInterval(timer);
alert('done');
}
} , 1000);
}
$("#knap").click(function() {
myTimer();
});
$("#reset").click(function() {
myTimer();
});
or you could do something along these lines:
var myTimer = function(){
var that = this,
time = 15,
timer;
that.set = function() {
console.log('setting up timer');
timer = setInterval(function(){
console.log('running time: ' + time);
},1000);
}
that.reset = function(){
console.log('clearing timer');
clearInterval(timer);
}
return that;
}();
and run when you need to:
myTimer.set();
myTimer.reset();
Clear the timer every time it's initalized, that way all you have to do is call the function again to reset the timer :
var timer;
function myTimer(sec) {
if (timer) clearInterval(timer);
timer = setInterval(function() {
$('#timer').text(sec--);
if (sec == -1) {
clearInterval(timer);
alert('done');
}
}, 1000);
}
$("#knap, #reset").click(function() {
myTimer(15);
});
FIDDLE
You could re-write your myTimer() function like so:
function myTimer() {
var sec, timer = null;
myTimer = function() {
sec = 15;
clearInterval( timer );
timer = setInterval(function() {
$('#timer').text(sec--);
if (sec == -1) {
clearInterval(timer);
alert('done');
}
} , 1000);
};
myTimer();
}
Now, whenever you call myTimer(), the setInterval gets reset.
Here's an approach that is more in tune with the way JS was designed (as a functional language for those who still don't know). Rather than relying on a global variable, use a closure:
$("#knap").click(function start()//named callback to bind && unbind:
{
$(this).unbind('click');//no need to start when started
$("#reset").unbind('click').click((function(timer)
{//timer is in scope thanks to closure
return function()
{//resets timer
clearInterval(timer);
timer = null;
$('#knap').click(start);//bind the start again
//alternatively, you could change the start button to a reset button on click and vice versa
}
})(setInterval((function(sec)
{
return function()
{
$('#timer').text(sec--);
if (sec === -1)
{
$('#reset').click();//stops interval
$('#reset').unbind('click');//no more need for the event
alert('done');
}//here's the interval counter: 15, passed as argument to closure
})(15),1000)));//set interval returns timer id, passed as argument to closure
});
Now I will admit this is rather messy (and untested) but this way there reset event is only available when it's necessary, and you're not using any globals. But crucially, this is where JS's power lies: functions as 1st class objects, passing them as arguments and return values... just go function-crazy :)
I've set up a working Fiddle, too
You could also use a jQuery timer plugin, then you don't need to pass around the Variable.
Plugin: http://archive.plugins.jquery.com/project/timers
Example for the plugin: http://blog.agrafix.net/2011/10/javascript-timers-mit-jquery/

Add duration to JS setTimeout after the timer is running

I'm trying to figure out a way to emulate AS3's Timer class.
If you're not familiar, one of the cool things you can do is add duration to the timer even if it's already running. This functionality has a lot of very nice uses.
Anyone have any thoughts on doing this in js?
I'm not familiar with this class, but you can easily create something similar in JavaScript:
function Timer(callback, time) {
this.setTimeout(callback, time);
}
Timer.prototype.setTimeout = function(callback, time) {
var self = this;
if(this.timer) {
clearTimeout(this.timer);
}
this.finished = false;
this.callback = callback;
this.time = time;
this.timer = setTimeout(function() {
self.finished = true;
callback();
}, time);
this.start = Date.now();
}
Timer.prototype.add = function(time) {
if(!this.finished) {
// add time to time left
time = this.time - (Date.now() - this.start) + time;
this.setTimeout(this.callback, time);
}
}
Usage:
var timer = new Timer(function() { // init timer with 5 seconds
alert('foo');
}, 5000);
timer.add(2000); // add two seconds
Clear the timeout, then set a new timeout to the new desired end time.
Wrap the function with another one, and when the timer runs out, test to see if an extra time variable has been set. If it has, start again with the new time, otherwise execute the function.
A quickly hacked together script might look like:
function test() {
tim = new timer(function () { alert('hello'); }, 5000);
}
function extend() {
if (tim) { tim.addTime(5000); }
}
function timer(func, time) {
var self = this,
execute = function () {
self.execute()
};
this.func = func;
this.extraTime = 0;
setTimeout(execute, time);
};
timer.prototype.execute = function () {
var self = this,
execute = function () {
self.execute()
};
if (this.extraTime) {
setTimeout(execute, this.extraTime);
this.extraTime = 0;
} else {
this.func();
}
};
timer.prototype.addTime = function (time) {
this.extraTime += time;
}
<input type="button" value="Start" onclick="test()">
<input type="button" value="Extend" onclick="extend()">
There you go hope it helps :) just call setInterval with the time you want to have.
Edit: added stop and start in case you want to stop your loop :p
function Timer(defaultInterval, callback){
var interval = defaultInterval;
var running = true;
function loop(){
callback();
if(running){
setTimeout(function(){
loop();
}, interval);
}
}
loop();
return {
setInterval: function(newInterval){
interval = newInterval;
},
stop: function(){
running = false;
},
start: function(){
if(running===false){
running = true;
loop();
}
},
add: function(milliToAdd){
interval += milliToAdd*1;
}
}
}
var myTimer = Timer(250, function() { process code here });
myTimer.setInterval(1000); // sets interval to 1 second
myTimer.stop(); // stops the function
myTimer.start(); // re-starts the loop;
function Timer(func, delay) {
var done = false;
var callback = function() {
done = true;
return func();
};
var startTime = Date.now();
var timeout = setTimeout(callback, delay);
this.add = function(ms) {
if (!done) {
this.cancel();
delay = delay - (Date.now() - startTime) + ms;
timeout = setTimeout(callback, delay);
}
};
this.cancel = function() {
clearTimeout(timeout);
};
this.immediately = function() {
if (!done) {
this.cancel();
callback();
}
};
};
quick test in the console
start = Date.now();
t = new Timer(function() { console.log(Date.now() - start); }, 1000);
t.add(200);
start = Date.now();
t = new Timer(function() { console.log(Date.now() - start); }, 1000000);
t.immediately();
t.immediately();
you can add negative times too.
start = Date.now();
t = new Timer(function() { console.log(Date.now() - start); }, 1000);
t.add(-200);
Here's my shot. It keeps track of when the timer was set, and adds the difference to the specified time when you add time.
var Timer = {
set: function(p_function, p_time)
{
var d = new Date();
this.timeStarted = d.getTime();
this.func = p_function;
this.timeout = setTimeout(p_function, p_time);
console.log('timer started at ' + (this.timeStarted / 1000) + ' seconds');
},
add: function(p_time)
{
var d = new Date(),
diff = d.getTime() - this.timeStarted,
newTime = diff + p_time;
if (this.timeout)
{
clearTimeout(this.timeout);
}
this.timeout = setTimeout(this.func, newTime);
this.timeStarted = d.getTime();
}
};
var myTimer = Object.create(Timer);
myTimer.set(function() {
var d = new Date();
console.log('Timer fired at ' + (d.getTime() / 1000) + ' seconds');
}, 10000);
setTimeout(function () {
myTimer.add(5000);
}, 5000);
Here's a jsFiddle
Please note that due to overhead of calculation and function calls, this may be a couple milliseconds off.
I decided to throw my little rubber ducky into the pool.
var setTimeout2 = function(callback, delay) {
this.complete = false;
this.callback = callback;
this.delay = delay;
this.timeout = false;
this.dotimeout = function() {
this.timeout = setTimeout(function() {
this.complete = true;
this.callback.call();
}, this.delay);
};
this.start = Date.now();
this.add = function(delay) {
if (!this.complete) {
this.delay = this.delay - (Date.now() - this.start) + delay;
clearTimeout(this.timeout);
this.dotimeout.call();
}
};
return this;
};
usage
var start = Date.now();
var to = setTimeout2(function() {
document.write(Date.now() - start);
}, 3000);
to.add(3000);
similar to this approach but a little more compact / no proto

Categories

Resources