Javascript - Refresh - Memory Leak - javascript

I am seeing a major memory leak within Firefox and IE on my below code. To be fair, it could very well be my poor implementation and it needs changing, to allow Firefox and other browsers to garbage collect.
Does anyone have any suggestions on how to tweak the code to allow for a more efficient way of refreshing the page?
<input type="checkbox" onclick="sel1()" id="AutoRefresh">
<script type="text/javascript">
function sel1(){
var ref = document.getElementById('AutoRefresh').checked;
if(ref == true) {
setInterval(function(){
document.getElementById('dataRefreshButton').click(); }, 2000);
}
window.alert("Auto refresh on");
}
</script>

I think this will be better.
<script type="text/javascript">
function getdata(){
// get your data
}
var intGetData;
function sel1(){
var ref = document.getElementById('AutoRefresh').checked;
if(ref == true) {
intGetData = setInterval(getdata, 2000);
window.alert("Auto refresh on");
}
else{
clearInterval(intGetData);
window.alert("Auto refresh off");
}
}
</script>

Change setInterval to setTimeout. Your current code will set up a new interval to click the element every 2s when clicked. If you click once, you trigger an avalanche.
Or even better, you stop the interval:
var handle = null;
function sel1(){
var ref = document.getElementById('AutoRefresh').checked;
clearInterval(handle);
if (ref)
handle = setInterval(function(){
document.getElementById('dataRefreshButton').click();
}, 2000);
window.alert("Auto refresh on");
}

Related

clearInterval function not clearing setInterval function

I utilized this resource to structure my code: http://www.w3schools.com/jsref/met_win_clearinterval.asp
var intervalID = setInterval(function(){ ogpeWrapper() }, 10);
function ogpeWrapper() {
$("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll('<div id="colWrapperContainer"></div>');
}(jQuery);
function myStopFunction() {
if (document.getElementById('colWrapperContainer')) {
clearInterval(intervalID);
setIntervalID = undefined;
}
}
My ogpeWrapper function is running, but the clearInterval function is not.
Basically, once $("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll(''); runs, I want the interval to stop running it.
Edit - 12:24pm CST:
This is the base code I utilize to wrap the listed elements -
(function($) {
$("#breadcrumbAds, #breadcrumbWrapper, #containerTopParsys, #leftColWrapper, #rightColWrapper").wrapAll('<div id="colWrapperContainer"></div>');
})(jQuery);
This code works, but it doesn't process the change until after the DOM has completely loaded. I need the function to work as soon as those elementals are all available. So I need to use a setInterval to process the function, then clear the interval once the function is processed.
If anyone knows of another way to do this, besides a setIterval, please let me know.
You need to create a definite if else condition within the variable so you know exactly when it will start and when it will stop. Also, because the minimum millisecond interval timing is not consistent across browsers, although you want it to detect really fast, I would recommend a "safer" number and use 100 as the minimum instead. The .length method is a handy little way for you to check if an element is on a page; You can use it as a pseudo dynamic true/false conditional. Lastly, in your .wrapAll() tag, I swapped your single and double quotes, as it is best practice to do such.
var colWrapper = setInterval(function(){
if ($('div#colWrapperContainer').length > 0) {
var doNothing = "";
clearInterval(colWrapper);
} else {
$("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll("<div id='colWrapperContainer'></div>");
}
}, 100);
Here is a working example for your reference Wrap Example
Update:
Example for putting the script inside the <body> tag (no window.load/document.ready) so that it runs independently as soon as it is loaded.
<script type="text/javascript">//<![CDATA[
//http://stackoverflow.com/questions/33483000/clearinterval-function-not-clearing-setinterval-function/33483267#33483267
//Auto Wrap Solution
//Alexander Dixon [11-02-2015]
var wrapThese = $("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper");
var colWrapper = setInterval(function () {
if ($('div#colWrapperContainer').length > 0) {
var doNothing = "";
clearInterval(colWrapper);
} else {
wrapThese.wrapAll('<div id="colWrapperContainer"></div>').addClass('success');
}
}, 100);
//]]>
</script>

How do I make this javascript async while loop work?

I'm attempting to get a google gpt tag to refresh a maximum number of times if, when loaded, it comes back empty.
<script type="text/javascript">
googletag.cmd.push(function() {
var slot1 = googletag.defineSlot("/gtpConfigStuff",[300,600],"gtpConfigStuff")
.addService(googletag.pubads())
.setTargeting("pos", "BTF")
.setTargeting("URL", encodeURIComponent(window.location));
googletag.enableServices();
googletag.display("gtpConfigStuff");
googletag.pubads().addEventListener('slotRenderEnded', function(event) {
var tries = 0;
while (tries<=2 && event.isEmpty==true) {
//googletag.pubads().refresh([slot1]);
//setTimeout(function() {
tries++;
console.log(tries);
//}, 1000);
}
console.log("done");
});
});
</script>
With the above lines commented out it works as it should.
With the refresh function call it will loop indefinitely.
The setTimeout I thought might allow the refresh to finish.
Thanks.
Your script will load indefinitely because you're resetting your tries variable indefinitely
var tries = 0; // Set your variable here...
googletag.pubads().addEventListener('slotRenderEnded', function(event) {
// ...and not here. Otherwise it will always reset to 0 when the event triggers.
// "tries" will still be available in here though as a closure so you can still use it
if (tries<=2 && event.isEmpty==true) {
googletag.pubads().refresh([slot1]);
tries++;
}
});

need to set a timer for in javascript , then clear

I want to create a timer in JavaScript. I see the setTimeout(fn, 100) but unclear how to wrap this so it will clear itself at the end.
I tried doing
var buttonTimer = null;
$scope.backButton = function() {
if(buttonTimer === null){
$history.back();
}
buttonTimer = setTimeout(function(buttonTimer){
buttonTimer = null;
}, 100);
}
The whole point is to prevent the user from hitting this function too quickly.. and ignoring all subsequent clicks within that 100ms window, at the end of the window, clear the timer and resume accepting clicks
Since you are doing angular, I prepared a plnkr for demonstration:
http://plnkr.co/edit/5qrslKpmkglXTvEyYgBr?p=preview
Your code is almost Ok, the only problem is that you start a new timeout on every click. The effect is, that the callback fires multiple times and resets buttonTimer.
So the only change is:
var blocker = null;
$scope.backButton = function() {
if(blocker == null) {
blocker = setTimeout(function(){
blocker = null;
}, 1500);
// DO YOUR STUFF HERE
}
};
You can use throttle from lodash/underscore or Ramdajs.
for example
$scope.backButton=_.throttle(100,function(){/* do something here */});

setTimeout does bizarre things when executing in a tab that doesn't have focus [duplicate]

Is there a way to stop setTimeout("myfunction()",10000); from counting up when the page isn't active. For instance,
A user arrives at a "some page" and stays there for 2000ms
User goes to another tab, leaves "some page" open.
myfunction() doesn't fire until they've come back for another 8000ms.
(function() {
var time = 10000,
delta = 100,
tid;
tid = setInterval(function() {
if ( document.hidden ) { return; }
time -= delta;
if ( time <= 0 ) {
clearInterval(tid);
myFunction(); // time passed - do your work
}
}, delta);
})();
Live demo: https://jsbin.com/xaxodaw/quiet
Changelog:
June 9, 2019: I’ve switched to using document.hidden to detect when the page is not visible.
Great answer by Šime Vidas, it helped me with my own coding. For completeness sake I made an example for if you want to use setTimeout instead of setInterval:
(function() {
function myFunction() {
if(window.blurred) {
setTimeout(myFunction, 100);
return;
}
// What you normally want to happen
setTimeout(myFunction, 10000);
};
setTimeout(myFunction, 10000);
window.onblur = function() {window.blurred = true;};
window.onfocus = function() {window.blurred = false;};
})();
You'll see that the window blurred check has a shorter time set than normal, so you can set this depending on how soon you require the rest of the function to be run when the window regains focus.
You can do something like:
$([window, document]).blur(function() {
// Clear timeout here
}).focus(function() {
// start timeout back up here
});
Window is for IE, document is for the rest of the browser world.
I use almost the same approach as Šime Vidas in my slider
but my code is based on document.visibilityState for page visibility checking:
document.addEventListener("visibilitychange", () => {
if ( document.visibilityState === "visible" ) {
slideshow.play();
} else {
slideshow.pause();
}
});
About Page Visibility
API: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
What you'd have to do is set up a mechanism to set timeouts at small intervals, keeping track of total elapsed time. You'd also track "mouseenter" and "mouseleave" on the whole page (the <body> or something). When the short-term timeouts expire, they can check the window state (in or out) and not restart the process when the window is not in focus. The "mouseenter" handler would start all paused timers.
edit — #Šime Vidas has posted an excellent example.
I've finally implemented a variation of #Šime Vidas' answer, because the interval was still running if I opened another program and the browser window was not visible, but the page executing the interval was the active browser tab. So, I've modified the condition to document.hidden || !document.hasFocus(). This way, if the document is hidden or the document doesn't have the focus, the interval function just returns.
(function() {
var time = 10000,
delta = 100,
tid;
tid = setInterval(function() {
if ( document.hidden || !document.hasFocus() ) { return; }
time -= delta;
if ( time <= 0 ) {
clearInterval(tid);
myFunction(); // time passed - do your work
}
}, delta);
})();

Busy indicator race condition in Javascript

I have the following (javascript/jquery) code to show a busy indicator (after a delay) while an image is loading:
function imgUpdate(arg) {
var loaded = false;
$("#image").one("load", function(){
loaded = true;
$("#busyIndicator").hide();
});
setTimeout(function(){
if (!loaded) {
$("#busyIndicator").show();
}
}, 250);
$("#image")[0].src = arg;
}
Sometimes, the indicator comes up and stays up. How is this possible if the browser's javascript engine is single-threaded? (This is on Firefox 3, by the way.)
One note: this seems to happen when the image being loaded is already cached.
Another note: if I log to my firebug console, all of the lines in imgUpdate are executed, but a log message inside the onload handler never prints on subsequent calls to imgUpdate.
Is there any other javascript on the page that breaks? If so, this may not be a race condition -- JS could simply stop executing before the busyIndicator is hidden again...
I'm hard pressed to replicate this.
Here is the implementation of what you're doing:
A version using caching:
http://jsbin.com/uwuho
A version with caching being prevented: (uses parameter to avoid caching)
http://jsbin.com/oguvi
Hit F5/Ctrl-F5 to see it go. (in particular with the version which prevents caching)
With or without caching neither version is doing what you'd described.
Your problem probably lies elsewhere.
Clearing the image's src tag seems to fix the problem:
function imgUpdate(arg) {
var loaded = false;
$("#image").one("load", function(){
loaded = true;
$("#busyIndicator").hide();
});
setTimeout(function(){
if (!loaded) {
$("#busyIndicator").show();
}
}, 250);
$("#image")[0].src = "";
$("#image")[0].src = arg;
}
You might want to clear the timeout in your callback so that it won't fire if the image is loaded.
var timer = null;
function imgUpdate(arg) {
var loaded = false;
timer = setTimeout(function(){
$("#busyIndicator").show();
timer = null;
}, 250);
$("#image").one("load", function(){
if (timer) {
clearTimeout(timer);
timer = null;
}
$("#busyIndicator").hide();
});
$("#image")[0].src = arg;
}

Categories