How do I reset the setInterval timer? - javascript

How do I reset a setInterval timer back to 0?
var myTimer = setInterval(function() {
console.log('idle');
}, 4000);
I tried clearInterval(myTimer) but that completely stops the interval. I want it to restart from 0.

If by "restart", you mean to start a new 4 second interval at this moment, then you must stop and restart the timer.
function myFn() {console.log('idle');}
var myTimer = setInterval(myFn, 4000);
// Then, later at some future time,
// to restart a new 4 second interval starting at this exact moment in time
clearInterval(myTimer);
myTimer = setInterval(myFn, 4000);
You could also use a little timer object that offers a reset feature:
function Timer(fn, t) {
var timerObj = setInterval(fn, t);
this.stop = function() {
if (timerObj) {
clearInterval(timerObj);
timerObj = null;
}
return this;
}
// start timer using current settings (if it's not already running)
this.start = function() {
if (!timerObj) {
this.stop();
timerObj = setInterval(fn, t);
}
return this;
}
// start with new or original interval, stop current interval
this.reset = function(newT = t) {
t = newT;
return this.stop().start();
}
}
Usage:
var timer = new Timer(function() {
// your function here
}, 5000);
// switch interval to 10 seconds
timer.reset(10000);
// stop the timer
timer.stop();
// start the timer
timer.start();
Working demo: https://jsfiddle.net/jfriend00/t17vz506/

Once you clear the interval using clearInterval you could setInterval once again. And to avoid repeating the callback externalize it as a separate function:
var ticker = function() {
console.log('idle');
};
then:
var myTimer = window.setInterval(ticker, 4000);
then when you decide to restart:
window.clearInterval(myTimer);
myTimer = window.setInterval(ticker, 4000);

Here's Typescript and Nuxt 3 version if anyone's interested :]
Composable useInterval.ts
useInterval.ts
export function useInterval (callback: CallableFunction, interval: number): Interval { // Argument interval = milliseconds
return new Interval(callback, interval)
}
class Interval {
private timer = null
constructor (private callback, private interval) {
}
start () {
this.timer = setInterval(this.callback, this.interval)
}
stop () {
clearInterval(this.timer)
this.timer = null
}
restart (interval = 0) {
this.stop()
if (interval) {
this.interval = interval
}
this.start()
}
}
Example usage
const interval = useInterval(function() {
// your function here
}, 5000);
// Reset the interval and set it to 10s
interval.reset(10000);
// Stop the interval
interval.stop();
// Start the interval
interval.start();

Related

How to pause setTimeout and then continue it?

https://jsfiddle.net/mhLaj3qy/1/
const changeTimeset = setTimeout(()=>{
if (is_paused) return;
bgImage.style.backgroundImage = array[current]
changeBackgroundImages(data, ++current % array.length)
}, a)
function chandgeBackgroundImageOnMouse() {
samoyed.addEventListener("mouseover", ()=>{
bgImage.style.backgroundImage = house
is_paused = true
})
samoyed.addEventListener("mouseleave", ()=>{
is_paused = false
})
}
chandgeBackgroundImageOnMouse()
}
How to pause setTimeout and then continue it? It should be like when it hovered on text - picture stops auto slider, when it mouseout - auto slider is working
Here i tried to do it with it_paused = false/true. But nothing succeeded. What am i doing wrong?
In this case, you may try using setInterval instead of setTimeout.
About setInterval:
https://www.w3schools.com/jsref/met_win_setinterval.asp
In fact, setTimeout internally can't be paused, but we can work around, it by when pause clearing the old setTimeout and checking the difference in time, and setting it in a variable called remaining, then when we resume creating a new setTimeout with the remaining time.
class Timer {
constructor(callback, delay) {
this.remaining = delay
this.callback = callback
this.timerId = undefined;
this.start = undefined;
this.resume()
}
pause() {
window.clearTimeout(this.timerId);
this.timerId = null;
this.remaining -= Date.now() - this.start;
};
resume() {
if (this.timerId) {
return;
}
this.start = Date.now();
this.timerId = window.setTimeout(this.callback, this.remaining);
};
}
const pause = document.getElementById('pause');
const resume = document.getElementById('resume');
var timer = new Timer(function() {
alert("Done!");
}, 5000);
pause.addEventListener('click', () => {
timer.pause();
})
resume.addEventListener('click', () => {
timer.resume();
})
<button id="pause">Pause</button>
<button id="resume">Resume</button>

Clear interval inside object method

This code is part of a game where the user has a certain amount of time to input an answer.
I want to be able to clear the interval from outside of the object if the user decides to submit an answer before the allotted time has elapsed.
I have tried returning the interval with an ID so that I can call it later and whilst this does allow me to clear it from outside the outside the object, it means that the code inside the interval function is never run.
const clock = {
timer: 30,
countdown() {
let interval = setInterval(function () {
selectors.timerDisplay.textContent = clock.timer
clock.timer--
if (clock.timer < 0) {
clearInterval(interval)
selectors.wordSubmit.click();
}
}, 1000)
},
}
I appreciate I may have simply set myself up badly to clear this interval, therefore any suggestions on how I could improve it would be appreciated.
Thanks in advance.
You can use Arrow functions to leverage the context of this from your object clock
Add a method i.e clear.
Use this context to reference your inner attributes.
const clock = {
timer: 3,
interval: 0,
reset() {
this.timer = 3;
this.interval = 0;
},
clear() {
clearInterval(this.interval);
this.reset();
},
countdown() {
this.interval = setInterval(() => {
//selectors.timerDisplay.textContent = clock.timer
this.timer--;
console.log(this.timer)
if (this.timer < 0) {
clearInterval(this.interval)
//selectors.wordSubmit.click();
}
}, 1000);
},
}
clock.countdown();
setTimeout(function() {
clock.clear();
}, 1500)
See? the interval function ends after 1.5secs
You can expose a method to clear the interval
const selectors = document.querySelector('div');
const clearTimer = document.querySelector('button');
const clock = {
timer: 5,
// Initiate the interval
int: null,
// This exposes a way to clear the interval outside of the object
clearTimer() {
clearInterval(this.int);
},
countdown() {
// This is where you define this.int
this.int = setInterval(() => {
//selectors.timerDisplay.textContent = clock.timer
selectors.innerText = clock.timer.toString();
clock.timer--
console.log(clock.timer);
if (clock.timer < 0) {
this.clearTimer();
//selectors.wordSubmit.click();
}
}, 1000)
},
}
clock.countdown();
clearTimer.addEventListener('click', () => {
clock.clearTimer();
})
<div>clock.timer</div>
<button>clear timer</button>
As has been suggested in the comments, simply return the interval so it can be stopped later. For example
countdown() {
let interval = setInterval(function () {
selectors.timerDisplay.textContent = clock.timer
clock.timer--
if (clock.timer < 0) {
clearInterval(interval)
selectors.wordSubmit.click();
}
}, 1000)
return interval // added this line
},
Then, consumers can cancel the interval when they want
const interval = clock.countdown()
// and later...
clearInterval(interval)

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() {

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/

Repeating setTimeout

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.

Categories

Resources