If I have the following code:
var myfunc = function() { alert('wow'); };
var t=setTimeout(myfunc, 300);
Is there anything I can do with the id stored in t to verify the timer's duration and callback? I'm trying to verify the timer's properties directly so I don't have to actually run it 'till timeout in my unit tests.
Nope, can't be done.
What you can do instead is track them differently, something like this:
var timeouts = [{
fn: myfunc,
timeout: 300
}];
for(var i = 0; i < timeouts.length; i++){
timeouts[i].id = window.setTimeout(timeouts[i].fn, timeouts[i].timeout);
}
The returned ID is internal to the browser, so you can't do much with it. But since you know the duration and callback when you initiate the timer, you could just as well wrap the whole thing in a Timer class that does everything for you:
function Timer(callback, timeout) {
this.callback = callback;
this.timeout = timeout;
this.id = window.setTimeout(callback, timeout);
}
Timer.prototype.cancel = function() {
window.clearTimeout(this.id);
}
Timer.prototype.fire = function() {
this.cancel();
this.callback();
}
Then you just create timers and access their properties like this:
t = new Timer(myfunc, 300);
alert(t.timeout);
Related
My question is: is there a unique way to reset timers without knowing their ID in Javascript? I tried using this code:
var maxId = setTimeout(function(){}, 0);
for(var i=0; i < maxId; i+=1) {
clearTimeout(i);
}
I'm aware this would search for any timer and clear any timer, but nothing happens and I think the console even gives me an error when I use it as a bookmarklet. Also, the value of the timer is stored in innerHTML, as such:
<div id="timer">
<div id="timer-minutes" class="timer-fields">00:00</div>
</div>
A unique way to look at this problem is to override the default functionality of setTimeout. By augmenting the function you can then tap into all uses of setTimeout on the page. Then you can simply create a new method to clear all timeouts.
In the code below, I hot-wire the built-in function (setTimeout) with my own version. As long as this code executes before other scripts on the page, I then can keep track of all invocations of the function on the page. Perhaps you could even store the setTimeouts by callee.
(function(win)
{
var _originalSetTimeout = setTimeout; //Store built-in function
var timers = []; //Maintain a collection of timers
win.setTimeout = function(func, delay) //Hijack the built-in function with your own
{
var timer = _originalSetTimeout(func, delay); //Invoke the built in
timers.push(timer); //Store the timer to your private array
};
win.clearAllTimeouts = function() //Create a new function on the window for resetting all timers
{
for(var i=0,length=timers.length;i<length;i++)
{
win.clearTimeout(timers[i]);
}
};
}(window));
Once this function is wired up you then can test with the following code:
var x=0;
function Test()
{
x++;
console.log('test: ' + x);
setTimeout(Test, 1000);
if(x === 5)
{
clearAllTimeouts();
console.log('all timeouts cleared!');
}
}
Test();
The counter will log up to 5, then once it's it the clearAllTimeouts() function is invoked.
See it in action here:
http://jsbin.com/bulayuro/1/edit
If I have a function like so:
function x()
{
animate(a, 2000);
animate(b, 3000);
animate(c, 4000);
}
Where - a, b & c - are variables representing elements on the page, and the number is a parameter passed to an animate() function that uses it as a duration value for a timeout, like so:
function animate(src, dur)
{
setTimeout(function() {
src.style.opacity = 1;
}, dur);
}
Everything so far is fine, but if I want the ability to break out of the animation loop, how do I go about it? Will clearTimeout() be what I'm looking for?
Variables that have been assigned a timeout, may be passed to the clearTimeout function, which will cease the function. You can store these variables in an array and easily clear all timeouts by iterating this array and passing the timeout to the clearTimeout function.
var timeouts = [];
/* Save timeouts into a variable and push to an array */
function animate(src, dur)
{
var timeout = setTimeout(function() {
src.style.opacity = 1;
}, dur);
timeouts.push(timeout);
}
/** Clear all timeouts**/
function clearTimeouts(){
for(var i = 0; i < timeouts.length; i++){
clearTimeout(timeouts[i]);
}
}
//Create timeouts
x();
//Invoke clearTimeouts
clearTimeouts();
Yes, clearTimeout() is the right way to go:
function animate(src, dur)
{
return setTimeout(function() {
src.style.opacity = 1;
}, dur);
}
And save returned identifier:
function x()
{
var aId = animate(a, 2000);
var bId = animate(b, 3000);
var cId = animate(c, 4000);
}
Later you simply call clearTimeout(aId) or whichever you desire. BTW there is no loop in your code, setTimeout() executes only once, as opoosed to setInterval().
Right now i have this 1 minute timer in my background page that runs forever i would like to be able to start and stop it from an options page.
chrome.browserAction.setBadgeBackgroundColor({color:[0, 0, 0, 255]});
var i = 1;
window.setInterval(function(timer) {
chrome.browserAction.setBadgeText({text:String(i)});
i++;
}, 60000);
setInterval() method of the Window object schedules a function to be invoked repeatedly at intervals of the specified number of milliseconds. setInterval() returns an opaque value that can be passed to clearInterval() to cancel any future invocations of the scheduled function. Read more about How Javascript Timers work. With that you can write something like this:
My.Controller = {};
(function() {
var interval = 10;
var timer = null;
function init (param) {
// initialisations if any
}
// Override the default interval of 10 seconds by passing new interval
function startAction (param, tInterval) {
// Set a timer
var ti = (!tInterval) ? interval : tInterval;
timer = setInterval(My.Controller.action, ti * 2000);
}
function action () {
// Logic here
}
function stopAction () { clearInterval(timer); }
var c = My.Controller;
c.init = init;
c.startAction = startAction;
c.stopAction = stopAction;
})(); // end Controller
Now you can say My.Controller.startAction() to start the timer and and My.Controller.stopAction() to stop.
Read and explore about namespaces in JavaScript.
Hope this helps.
I have a setInterval function like below on a Divbox so if I leave a divbox, this setInterval is triggered:
setInterval("playthis()", 1000);
What I want it to do: If I leave the divbox and lets say within the next 2 second rehover it, the setInterval should not triggered.
Is this possible?
You can use cousins setTimeout and clearTimeout to set a function callback that invokes your setInterval only after 2 uninterrupted seconds:
var handle = null;
function yourDivboxLeaveHandler() {
handle = setTimeout(startPlay, 2000);
}
function yourDivboxHoverHandler() {
if (handle !== null) {
clearTimeout(handle);
handle = null;
}
}
function startPlay() {
setInterval(playthis, 1000); // use function references please, not eval
handle = null;
}
You will want much better variable/function names than this though.
Yes. Just make some creative use of clearInterval().
In other words, no, such a feature doesn't come out-of-the-box, but you can build it yourself by calling clearInterval() if the mouse re-enters the divbox before the interval is triggered.
For example:
var divBox = document.getElementById('MyDivBox');
var TimeoutHandle = null;
divBox.onmouseover = function()
{
if ( TimeoutHandle != null )
{
clearTimeout(TimeoutHandle);
}
}
divBox.onmouseout = function()
{
TimeoutHandle = setTimeout(function()
{
TimeoutHandle = null;
setInterval(playthis, 1000);
}, 2000);
}
First of all is a bad practice to have the code evalued in a setInterval so you should avid double quotes. Then you can clear the interval like this:
var int = setInterval(playthis, 1000);
clearInterval(int)
Greetings,
I have the following JS code:
var reloadTimer = function (options) {
var seconds = options.seconds || 0,
logoutURL = options.logoutURL,
message = options.message;
this.start = function () {
setTimeout(function (){
if ( confirm(message) ) {
// RESET TIMER HERE
$.get("renewSession.php");
} else {
window.location.href = logoutURL;
}
}, seconds * 1000);
}
return this;
};
And I would like to have the timer reset where I have the comment for RESET TIMER HERE. I have tried a few different things to no avail. Also the code calling this block is the following:
var timer = reloadTimer({ seconds:20, logoutURL: 'logout.php',
message:'Do you want to stay logged in?'});
timer.start();
The code may look familiar as I found it on SO :-)
Thanks!
First of all, you need to use the new operator in var timer = new reloadTimer, and also reloadTimer should be capitalized into ReloadTimer to signify that it needs to be used with new.
The reason why you need new is because the function references this and when used without new this will be the global scope instead of the instance it self.
To reset a timer you just call window.clearTimeout with the timers reference as the parameter
var timer = window.setTimeout(....
...
window.clearTimeout(timer);
UPDATE
By RESET do you actally mean to restart the timer?
If so, just use setInterval instead of setTimeout
UPDATE 2
And here is a slightly better approach (if you still want to use such a class to encapsulate something so trivial)
var ReloadTimer = function(options){
var seconds = options.seconds || 0, logoutURL = options.logoutURL, message = options.message;
var timer;
return {
start: function(){
timer = setInterval(function(){
if (confirm(message)) {
$.get("renewSession.php");
}
else {
clearInterval(timer);
window.location.href = logoutURL;
}
}, seconds * 1000);
}
};
};
var myTimer = new ReloadTimer({
seconds: 20,
logoutURL: 'logout.php',
message: 'Do you want to stay logged in?'
});
myTimer.start();
You could execute the function again with the same parameters?