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

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

Related

Not able to kill previous counter when countdown is placed in a loop

I am using a simple countdown as such below which is working fine except when it is placed in the loop. During looping both previous and new counter remains working .I want to kill the previous counter and start with a new, which i am not able to achieve. Can anybody help on this please
function triggerEvery60Sec(){
var myCounter = new Countdown({
seconds:5, // number of seconds to count down
onUpdateStatus: function(sec){console.log(sec);}, // callback for each second
onCounterEnd: function(){ alert('counter ended!');} // final action
});
myCounter.start();
}
function Countdown(options) {
var timer,
instance = this,
seconds = options.seconds || 10,
updateStatus = options.onUpdateStatus || function () {},
counterEnd = options.onCounterEnd || function () {};
function decrementCounter() {
updateStatus(seconds);
if (seconds === 0) {
counterEnd();
instance.stop();
}
seconds--;
}
this.start = function () {
clearInterval(timer);
timer = 0;
seconds = options.seconds;
timer = setInterval(decrementCounter, 1000);
};
this.stop = function () {
clearInterval(timer);
};
}
Instead of declare your variable in the loop, maybe should you declare it before, and manipulate it during your loop.
var myCounter = null;
function triggerEvery60Sec(){
myCounter = new Countdown({
seconds:5, // number of seconds to count down
onUpdateStatus: function(sec){console.log(sec);}, // callback for each second
onCounterEnd: function(){ alert('counter ended!');} // final action
});
myCounter.start();
}

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.

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.

Looping functions with timeout

I want to have two functions (an animation downwards and animation upwards) executing one after the other in a loop having a timeout of a few seconds between both animations. But I don't know how to say it in JS …
Here what I have so far:
Function 1
// Play the Peek animation - downwards
function peekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-150px";
tile2.style.top = "-150px";
peekAnimation.execute();
}
Function 2
// Play the Peek animation - upwards
function unpeekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "0px";
tile2.style.top = "0px";
peekAnimation.execute();
}
And here's a sketch how both functions should be executed:
var page = WinJS.UI.Pages.define("/html/updateTile.html", {
ready: function (element, options) {
peekTile();
[timeOut]
unpeekTile();
[timeOut]
peekTile();
[timeOut]
unpeekTile();
[timeOut]
and so on …
}
});
You can do this using setTimeout or setInterval, so a simple function to do what you want is:
function cycleWithDelay() {
var delay = arguments[arguments.length - 1],
functions = Array.prototype.slice.call(arguments, 0, arguments.length - 1),
pos = 0;
return setInterval(function () {
functions[pos++]();
pos = pos % functions.length;
}, delay);
}
Usage would be like this for you:
var si = cycleWithDelay(peekTile, unpeekTile, 300);
and to stop it:
clearInterval(si);
This will just cycle through the functions calling the next one in the list every delay msec, repeating back at the beginning when the last one is called. This will result in your peekTile, wait, unpeekTile, wait, peekTile, etc.
If you prefer to start/stop at will, perhaps a more generic solution would suit you:
function Cycler(f) {
if (!(this instanceof Cycler)) {
// Force new
return new Cycler(arguments);
}
// Unbox args
if (f instanceof Function) {
this.fns = Array.prototype.slice.call(arguments);
} else if (f && f.length) {
this.fns = Array.prototype.slice.call(f);
} else {
throw new Error('Invalid arguments supplied to Cycler constructor.');
}
this.pos = 0;
}
Cycler.prototype.start = function (interval) {
var that = this;
interval = interval || 1000;
this.intervalId = setInterval(function () {
that.fns[that.pos++]();
that.pos %= that.fns.length;
}, interval);
}
Cycler.prototype.stop = function () {
if (null !== this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
Example usage:
var c = Cycler(peekTile, unpeekTile);
c.start();
// Future
c.stop();
You use setInterval() to call unpeekTile() every 1000 milliseconds and then you call setTimeOut() to run peekTile() after 1000 milliseconds at the end of the unpeekTile() function:
function peekTile() {
var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
// Reposition tiles to their desired post-animation position
tile1.style.top = "-150px";
tile2.style.top = "-150px";
peekAnimation.execute();
}
function unpeekTile() {
/* your code here */
setTimeout(peekTile, 1000);
}
setInterval(unpeekTile, 1000);
Check out the fiddle
var animation = (function () {
var peekInterval, unpeekInterval, delay;
return {
start: function (ip) {
delay = ip;
peekInterval = setTimeout(animation.peekTile, delay);
},
peekTile: function () {
//Your Code goes here
console.log('peek');
unpeekInterval = setTimeout(animation.unpeekTile, delay);
},
unpeekTile: function () {
//Your Code goes here
console.log('unpeek');
peekInterval = setTimeout(animation.peekTile, delay);
},
stop: function () {
clearTimeout(peekInterval);
clearTimeout(unpeekInterval);
}
}
})();
animation.start(1000);
// To stop
setTimeout(animation.stop, 3000);
​
I can't use this instead of animation.peekTile as setTimeout executes in global scope

How do I reset the setInterval timer?

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

Categories

Resources