Ok so this is starting to make me go a little crazy.
I've got a code for a timer tracker. You enter a time and it will calculate how long until the item will go on bid and when the bid phase will end. You can set an alarm as well.
My problem is that I am working with local variables. It all works fine until you delete the row. If the row is deleted, the interval will continue and the alarm will still go off. I've been thinking of a way to go around this. The only thing I can think of is checking if the row exists inside the insRow function but I'm not sure how to do that. If that's possible I could add it to this if statement:
if(noticeTime[1] === -6) {
clearInterval(interval);
}
http://jsfiddle.net/t7h9tbzf/
setInterval returns a numeric ID that you can store as a data- attribute in the inserted row, with something like
const interval = window.setInterval(alarm, 1000);
new_row.dataset.intervalID = interval;
Then, before deleting the row, clear the interval:
window.clearInterval(row.dataset.intervalID);
Related
I've encountered a very badly designed website, and most of the "dynamic" content on the site is changed within setTimeout/setInterval functions.
There is one very annoying setInterval function which checks page activity very quickly, and I would like to override this function.
What I tried is clearing all the setInterval values, one by one to check if the function stopped. Also, clearing all the possible setInterval values like this: for(let i = 0; i < 1000; i++) clearInterval(i);, stops the "dynamic" page rendering, WHICH I DONT WANT TO
Question: 1. is there any way to look into the interval or timeout function and clear them?
2. is there a better way?
My current solution: I'm overriding the setInterval and setTimeout before page loaded, and log the function .toString() within.
The short answer is no, you cannot determine anything about the setTimeout/setInterval callback given a timerId. It sounds as if you don't have access to edit the underlying Javascript to prevent this action. If you can get your JS to load before the code in the page, then what you can do is replace setInterval or setTimeout with your own code, where you can increase the interval to whatever you want. For example:
let setTimeoutOld = setTimeout;
setTimeout = (cb, interval) => {
if (interval < 1000) {
interval = 1000;
}
setTimeoutOld(cb, interval);
}
Now if the page does something like:
setTimeout(() => { console.log('fired') }, 1);
The timeout won't fire until at least 1000ms have passed. If you only wanted to modify a specific setTimeout based on the contents of the cb, you could do what you mentioned in your work-around: calling .toString() on the function and comparing it to some previously generated .toString() (partial or complete) and then doing whatever you wanted.
I assume you have access to code wherever it's setting timeout or interval.
So just take a global array and push it's output to it. Then iterate that array to clear everything.
For ex.
timeouts = [];
now, in code where there's timeout like
var timeout = setTimeout(<callback> , <interval> ); // push it's output to that global.
timeouts.push(timeout);
Then at the very end clear that.
for(time of timeouts) {
clearTimeout(time);
}
Similarly, for Interval.
Hope this is what you are looking for.
I am currently running a timer based script (once a week) that copies a couple of values from one range (source) to another (target).
The source range is the result of a query based on a import. Thus it goes through multiple calculation steps before displaying the proper result.
Usually this should be an easy task - just add a sleep timer to be sure and be done with it.
However, the script copies the data based on an unfinished calculation.
Here's how I approached the this:
I setup a cell that checks if the data was correctly copied (trigger cell)
Now, I could just run a timer on sunday every hour or so, checking if the trigger is true or false. But I was wondering if there is a way to do this with a loop.
I am fairly new to javascript so I'm not very confident with implementing possible solutions from the web.
It seems that loops can only be broken based on values within the loop. A do/while (while 'trigger' == false) loop for example just loops for 5 Minutes until it times out. I think a function call with the function calling itself should do the trick, but I couldn't figure out how to do this properly. My version just seems to run once and break - even when I change the triggervalue manually to force a loop.
function looper(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("example");
var trigger = sheet.getRange("a1").getValue();
var source = sheet.getRange("b1:j1").getValues();
var target = sheet.getRange("b2:j2");
Utilities.sleep(5000)
if (trigger == false){
target.setValues(source);
looper;
}
}
In JavaScript, to call a function you need to use parentheses. So for the last line, try doing this: looper(); instead.
As far as I know we can clearInterval as:
var go = setInterval(function() {
console.log("go");
}, 5000);
clearInterval(go);
But for some reason in my javascript code I have same variable being assigned two time the setInterval. Now even if I clear it multiple times it doesn't get cleared. Example:
var go = setInterval(function(){
console.log("go");
}, 1000);
var go = setInterval(function(){
console.log("go");
}, 1000);
clearInterval(go);
clearInterval(go);
clearInterval(go);
clearInterval(go);
My questions is:
What is going on here? How does javascript deal with this situation? What's wrong with go? Why doesn't it get cleared?
You cannot. You've overwritten the previous timer id. It's lost.
Only the second interval, with the id that is currently stored in the variable, will get cleared, regardless how often you call clearInterval.
You will need multiple variables (or a datastructure of timers, e.g. an array):
var go1 = setInterval(function(){
console.log("go 1");
}, 1000);
var go2 = setInterval(function(){
console.log("go 2");
}, 1000);
clearInterval(go1);
clearInterval(go1); // nothing will happen
clearInterval(go2);
As mentioned in some of the comments, what you've done here is reassign your go variable. Each call to setInterval returns a different id. Once you've reassigned the only variable referencing that value, the previous value is lost.
When it comes to unique identifiers, it's batter to keep an expandable list of them so that you won't lose the identifier for the process. I suggest making an array and pushing each new id to it (using it much like a stack), that way they are all in one place but are still able to be individually referenced:
var intervalIDs = []; //we would want something like this to be a global variable
//adding IDs to the array:
intervalIDs.push(window.setInterval(function(){console.log("go 1");}, 1000));
intervalIDs.push(window.setInterval(function(){console.log("go 2");}, 1000));
//now we know we can find both IDs in the future
//clearing an interval:
window.clearInterval(intervalIDs.pop()); //takes the last ID out of the array and uses it to stop that interval. this could be done in a for loop to clear every one you've set using the above method.
//OR if you happen to know the index (in the array) of a specific interval id you want to clear:
var index = /*index number*/;
window.clearInterval(intervalIDs.splice(index, 1)[0]);
The point is to ensure that you maintain the means of referencing your intervals (or anything else that acts similarly, for that matter).
I am working on a project in which I am dynamically generating many setInterval's, and so it is not possible to store their reference in a variable so that it could be used to clearInterval.
Just wanted to ask you guys if anyone has an idea of how to clearInterval on a particular div with an Id.
In my project, when setInterval is supposed to be cleared, I am also removing the element from document body. So when setInterval is called again, I can put a condition to check if the element with that particular id exists and only then I can execute the setInterval code.
Like this,
if(document.getElementById("char0") != null)
{
// execute the setInterval code.
}
But this approach will still take CPU time. I am dynamically generating around 150 setIntervals, not possible to create variable reference for them. Please help if you have any clue of how this could be achieved.
Try to store the interval variable in a closure:
var createInterval = function(elementId){
var interval;
interval = setInterval(function(){
if(document.getElementById(elementId) == null){
clearInterval(interval);
}else{
//Your code
}
},1000);
};
So you can create any number of intervals what you like and remove it when those DOM elements are gone.
createInterval('element1');
createInterval('element2');
createInterval('element3');
But as what #alexander-omara said, use only few interval to update all elements is better solution in term of CPU usage.
You can easily keep a reference to a interval ID on a DOM element:
var element = document.getElementById("char0");
element._someInterval = setInterval(function(){
//Some code.
}, 1000);
And then clear it using:
if(element._someInterval)
{
clearInterval(element._someInterval);
}
However, creating hundreds of intervals does not sound like a very efficient means of doing anything. You way want to create 1 interval, and loop over an array of elements.
You need to have interval variable to call clearinterval() properly.
If you create variables dynamically like "interval+divid" so each time you get Id, create variable name by this convention and clear the same.
I am using Selenium to test a web app that uses Dojo, and it uses java script to display certain elements. I want to wait until all of the elements are desplayed before I try to manipulate the page, however I am having trouble.
I have started by waiting for the dojo inFlight variable to be 0, this says that all ajax has finished. This doesn't always work because it seems to do some things on a timeout afterwards.
I have also tried repeatedly looking for the element, but this isn't too nice, as perhaps there is some javascript later which will use this field in some way.
So basically I want a method (in firefox at least) to query the javascript waiting to run on a setTimeout (or setInterval) I could even cope with a way of wrapping the built in call through a function of my own just to keep track of this.
Any thoughts or suggestions appreciated!
Every function in JavaScript can be replaced. Consider something like this:
window.originalSetTimeout = window.setTimeout;
window.setTimeout = function(func, delay, params) {
window.timeoutCounter++;
window.originalSetTimeout(window.timeoutCallback, delay, [func, params]);
}
window.timeoutCallback = function(funcAndParams) {
window.timeoutCounter--;
func = funcAndParams[0];
params = funcAndParams[1];
func(params);
}
Then:
selenium.waitForCondition("window.timeoutCounter == 0");
Whenever you call setTimeout of setInterval -- a timer id is returned.
Save that timer id in an array
Inside the function that you're calling on the timeout, pop that timer id off the array. Because we have to remove that id from the array as soon as the timer ends.
Any time you want to check the no. of active timers, just query the length of that array.
Another approach could be like this
const timeoutIndexThen = setTimeout(() => {});
// Some code that might call timeouts...
const timeoutIndexNow = setTimeout(() => {});
const countOfTimeoutsFiredSinceThen = timeoutIndexNow - timeoutIndexThen - 1;
It is based on the fact that each timeout will return a number that is greater by 1 on each call.
So we create some dummy timeout just to get this number at some point.
Then, after a while we call it again and we get a new number. Difference between those numbers is how many times interval was called in between.
Downside of this is that you have to actually create the timeout. Upside is that you don't have to modify original function.