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
Related
I've looked at many different solutions to this, none of which worked. I know it has something to do with setTimeout, but I don't know how to implement it properly.
function myfunction()
{
//the function
//wait for 1 second before it can be ran again
}
To clarify: I don't want to call the function at a regular interval, I want to be able to enforce a delay before the function can be called again.
var lastTime = 0;
function myFunction() {
var now = new Date().getTime(); // Time in milliseconds
if (now - lasttime < 1000) {
return;
} else {
lastTime = now;
}
// rest of function
}
You don't need to use setTimeout at all. The following is similar to other answers, but uses a closure to remember the last time the function ran rather than a global variable.
var myFunction = function() {
var lastTime = new Date();
return function() {
var now = new Date();
if ((now - lastTime) < 1000) return;
lastTime = now;
/* do stuff */
};
}());
I think the easiest solution would be to hold a boolean variable and reset it to true after a given delay.
fiddle
HTML
<button id="clickme">click me!</button>
JavaScript
var canGo = true,
delay = 1000; // one second
var myFunction = function () {
if (canGo) {
canGo = false;
// do whatever you want
alert("Hi!");
setTimeout(function () {
canGo = true;
}, delay)
} else {
alert("Can't go!");
}
}
$("#clickme").click(function(){
myFunction();
})
With this, you hold a boolean, canGo, and set it to true. If the function is run, it sets canGo to false and sets a setTimeout() for a time period of delay, in milliseconds. If you try to run the function again, it won't run and will, instead, alert("Can't go!"). This was just for demonstrative purposes; you don't need that part. After delay, canGo will be set to true, and you will be able to once more run the function.
var lastRan = 0;
var myFunction = function() {
var now = Date.now();
if(now-lastRan < 1000) {
return;
}
lastRan = now;
//rest of function
};
You may want to use throttle or debounce from underscore.js
http://underscorejs.org/#throttle
throttle_.throttle(function, wait, [options])
Creates and returns a
new, throttled version of the passed function, that, when invoked
repeatedly, 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.
By default, throttle will execute the function as soon as you call it
for the first time, and, if you call it again any number of times
during the wait period, as soon as that period is over. If you'd like
to disable the leading-edge call, pass {leading: false}, and if you'd
like to disable the execution on the trailing-edge, pass {trailing:
false}.
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);
http://underscorejs.org/#debounce
debounce_.debounce(function, wait, [immediate])
Creates and returns a
new debounced version of the passed function which will postpone its
execution until after wait milliseconds have elapsed since the last
time it was invoked. Useful for implementing behavior that should only
happen after the input has stopped arriving. For example: rendering a
preview of a Markdown comment, recalculating a layout after the window
has stopped being resized, and so on.
Pass true for the immediate parameter to cause debounce to trigger the
function on the leading instead of the trailing edge of the wait
interval. Useful in circumstances like preventing accidental
double-clicks on a "submit" button from firing a second time.
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
If you just want to run your function again after a set time, you can use setTimeout and pass it the function to run and the delay period in milliseconds.
function myfunction() {
//the function
//run again in one second
setTimeout(myfunction, 1000);
}
Edited based on poster's comments:
var waiting = false;
var myfunction = function() {
if (!waiting) {
//Run some code
waiting = setTimeout(function() {
waiting = false;
}, 1000);
}
};
I am trying to do a infinite loop, but it only works if I include an 'alert' on it. My code looks like this:
while( tocontinue ){
// Some code
alert('Accept to continue');
}
On this way, the user has to click to hide the alerts (for example, on Chrome), and then the loop continues correctly by itself. I need to implement this without any alert. I also tried this:
while( tocontinue ){
// Some code
tocontinue = false;
setTimeout(function(){tocontinue=true},500);
}
And with "window.setTimeout" too, and without the word "function(){}", but it doesn't work. I tried everything: some implementations on JavaScript of a sleep() function, calling the function each X time with setInterval, answers 1 and 3 on this post... :/
Thank you very much for your time.
I'm trying to implement a genetic algorithm, and I want to stop it when I decide (with a button that puts the global variable "tocontinue" to false). Meanwhile, I want a infinite loop.
Well, you won't be able to combine a true infinite loop with user interaction as they'll both be dependent on the same thread being able to work on them exclusively. But, you can get close with a near-instant interval.
var interval = setInterval(function () {
// some code
}, 10);
Possibly grouping a few iterations together for each round:
var interval = setInterval(function () {
var limit = 5;
while (limit--) {
// some code
}
}, 10);
But, the interval will keep the iteration going as quickly as possible while still giving some idle time for user interactions, like clicking a particular button to clear the interval.
document.getElementById('stopButton').addEventListener('click', function () {
clearInterval(interval);
}, false);
Example: http://jsfiddle.net/coiscir/xZBTF/
setInterval() may be more useful here.
function updateLoop() {
//All the code goes here
}
setInterval(updateLoop,500);
var reader = new XMLHttpRequest() || new ActiveXObject('MSXML2.XMLHTTP');
function loadFile() {
reader.open('get', 'ccc.txt', true);
reader.onreadystatechange = displayContents;
reader.send(null);
}
function displayContents() {
if(reader.readyState==4) {
var el = document.getElementById('main');
el.innerHTML = reader.responseText;
var data = el.innerHTML;
}
}
for(var I = 7; I >1; i+=3);
console.log(i)
I need to invoke some function given number of times through given delays. How should I do - declare variable for timer and pass it to invoking function for stopping timer in some moment or in loop (n times) invoke setTimeout once ( or some another approach to skeep delay time once) or other.Thanks.
edit to fix syntax eror
var timerID = null;
var n = 5;
this.timerID = setInterval(function(){
funcToInvoke(n,timerID){
if(invokeNumber == n){
clearInterval(timerID);
return;
}
else { do something}
}
},delay)
Yes, the approach is common and better than calling setTimeout in a loop (with a fixed number of times). It is more performant than that and also more flexible, because the interval will be stopped dynamically (might check for a future condition).
However, your code is a bit messy. Fixed:
// Assuming we a have
// n
// delay
// funcToInvoke
// and execute in context of some object
var that = this,
numberOfInvokes = 0;
this.timer = setInterval(function() {
// "this" points to the global object
if (numberOfInvokes == n)
clearInterval(that.timer);
else
funcToInvoke(numberOfInvokes);
numberOfInvokes++;
}, delay);
Your current method has a syntax problem, you can't have a function parameter like this.timerID). In fact, you should remove the whole funcToInvoke declaration, and declare n and timerID as local variables, so they will be available to the closure. Like this:
// Don't forget to define n here!
var n = 5;
// Change timerID to local var instead of property
var timerID = null;
timerID = setInterval(function(){
if(invokeNumber == n){
clearInterval(timerID);
return;
} else {
//do something
}
// You can setTimeout again anywhere in this function if needed
}, delay);
If you want an approximate delay, setInterval is probably ok. If you want a more precise interval, then repeated calls to setTimeout are better as you can adjust the length of time to the next call based on the time since the last call.
E.g. for a clock ticking every second, you can do repeated calls to setTimeout, setting the lag to just after the next full second.
We have started a timer with the following code. Is it possible to make window.setInterval method fail, if another timer is active on the method passed to the window.setInterval method?
GInterValId = window.setInterval("AutoRefresh()",parseInt(GRefreshInterval));
what you do is set up a system for this. Create an object that handle all your Timers:
var Timer = function () {
var currentTimer;
this.setTimer = function (func,time) {
if (currentTimer) {
alert("one timer already set");
}else {
currentTimer = setInterval(func,time);
}
}
this.stopTimer = function () {
clearInterval(currentTimer);
currentTimer = null;
}
}
Now you can use this code:
function doSomething() {...} // function example
function doSomethingElse() {...} // function example
var MyTimer = new Timer();
MyTimer.setTimer(doSomething,1000); // this will run
MyTimer.setTimer(doSomethingElse,1000); // this will not run
The second one will not run because the other one is active.
to make it work you have clear the first one.
MyTimer.stopTimer(); // will clear the current timer then you can run another one
MyTimer.setTimer(doSomethingElse,1000); // will run perfectly
If you keep track of the result result from window.setInterval(), you can stop the previous interval timer at any point.
var GInterValId = setInterval(AutoRefresh, parseInt(GRefreshInterval));
Then, when you want to reset it:
if (GInterValId) {
clearInterval(GInterValId);
}
GInterValId = setInterval(AutoRefresh, parseInt(GRefreshInterval));
Also note that I'm not passing a string to setInterval, but an actual JS function reference.
Or, if you just want to prevent another interval getting set:
var GInterValId = null; // initialize
// then, when you want to set it, check to see if it's already been set
if (GInterValId) {
GInterValId = setInterval(AutoRefresh, parseInt(GRefreshInterval));
}
I've been playing around with a site, in which I want to continue clicking a button for i amount of times every interval seconds.
My code is:
clickbidBtn1 = function() {
var bidBtn=document.getElementById("BidButton");
var interval = 15000;
for (var i=3; i>=0; i--){
setTimeout(bidBtn.click(1);,i*interval);
};
I've found out that GM executes all i amount of clicks at the same time, not with the intended delay. is there a way to delay the time of click? Say i wanted the function to click the button every 15 second for i amount of times.
I was thinking of giving it some more variables, and adding one variable in the settimeout code part, which only executes # the click, then comparing increased variables with current ones before going to the next settimeout... but haven't thought it through yet... it seems to be a complicated process for a simple process... :( i wll play around with it a bit
Use setInterval() for this.
One way:
var bidClickTimer = 0;
var numBidClicks = 0;
function clickbidBtn1 ()
{
var interval = 15000;
bidClickTimer = setInterval (function() {BidClick (); }, interval);
}
function BidClick ()
{
numBidClicks++;
if (numBidClicks > 3)
{
clearInterval (bidClickTimer);
bidClickTimer = "";
}
else
{
bidBtn.click (1);
}
}
clickbidBtn1 ();
Alternatively, without using global vars:
function clickbidBtn1 ()
{
var interval = 15000;
this.numBidClicks = 0;
this.bidClickTimer = 0;
this.BidClick = function () {
numBidClicks++;
if (numBidClicks > 3)
{
clearInterval (bidClickTimer);
bidClickTimer = "";
}
else
{
bidBtn.click (1);
}
};
this.bidClickTimer = setInterval (function(thisScope) {thisScope.BidClick (); }, interval, this);
}
clickbidBtn1 ();
Just to explain why your code does not work: You are calling the .click method immediately (putting () after a function name calls the function) and actually passing the return value of that function to setTimeout. The for loop is so fast that everything seem to happen at the same time.
You have to pass a function reference to setTimeout, e.g. an anonymous function:
setTimeout(function() {
bidBtn.click(1);
}, i*interval);