call clear interval function from another function without pass the interval variable - javascript

I need to clear an interval from another function
window.onload = function(){
var interval = null;
interval = setInterval(function(){
myFunction();
}, 1000);
function stop(){
clearInterval(interval);
}
}
without pass the interval variable
stop();
But I cannot make it working: when I call stop(); the interval continues...
How can I do?

There is an unexpected window.stop function which preexists yours.
That's another proof that global variables/functions are evil.
It might be this function which gets invoked instead of yours, depending on when the script is loaded.
Try to put your function in an object to protect namespaces:
It works in the StackOverflow fiddle:
var i = 0;
function myFunction() {
i++;
console.log(i);
}
var interval = null;
interval = setInterval(function() {
myFunction();
}, 1000);
var myObject = {
stop: function() {
console.log("stopping");
clearInterval(interval);
}
};
<button onclick="myObject.stop();">stop</button>
In the faulty jsFiddle, you get things in iframes, meaning window element is not the same. That's why your function is not invoked. That gives you that kind of errors:
You can put your script in the html to get it working:
jsfiddle

You could simply put something like var interval = null; at the beginning of the JavaScript outside of a function.
It's all about variable scope. A variable defined inside of a function is only available within that function. A variable defined outside of a function or object will be available globally to all functions.
What is the scope of variables in JavaScript?

I found also this solution working:
stop = function(){
clearInterval(interval);
}

The presumption on the answer you've checked as solution is wrong.
Your stop function wouldn't be working regardless of the fact that there are browsers supporting load stop command programmatically.
This [stop] command is a window property and can be deleted and\or be overwritten by a simple variable declaration or by a function with the same name anywhere on the script.
The reason you are not being able to call the stop function ( from the outside ), is because it's a closure.
Regards.
p.s.:
throwing it up on global scope will make it work, visit you fiddle
var i=0;
function myFunction(){
i++;
$('i').html(i);
}
interval = null;
interval = setInterval(function(){
myFunction();
}, 100);
stop = function(){
clearInterval(interval);
}

Related

Clearing an anonymous setInterval

How do you clear an anonymous setInterval function, like the following, so that i stops incrementing?
var i = 0;
setInterval(function(){
console.log(i);
i++;
}, 1000);
You need to store it in variable and then pass that variable in clearInterval.
var i = 0;
let variable = setInterval(function(){
i++;
console.log(i)
}, 1000);
//to clear interval after 5 seconds to check if it works
setTimeout(() => clearInterval(variable),5000)
This is highly NOT recommended!
Nevertheless, you can accomplish this by temporarily monkey-patching the window.setInterval function so you can capture the reference to the timer.
The following is a consolidated example, see further below for an implementation example.
// Declare a variable to store the interval
let rogueInterval = null;
//Override the setInterval method
const oldSetInterval = window.setInterval;
window.setInterval = (...args) => {
rogueInterval = oldSetInterval(...args);
}
var i = 0;
setInterval(function() {
console.log(i);
i++;
}, 1000);
// Reset it
window.setInterval = oldSetInterval;
// Will clear your rogueInterval after 5 seconds
setTimeout(() => {
clearInterval(rogueInterval);
}, 5000);
It sounds like you are including a script via script.src, therefore, you would need to put an inline script tag before to override the setInterval, and an inline script tag after to reset the setInterval:
<script> // JS that overrides the setInterval </script>
<script src="problem-file.js"></script>
<script> // JS that resets the setInterval </script>
Unfortunately, this approach assumes there is only one setInterval within the problem file, and the setInterval is not set asynchronously itself. If you absolutely needed to, you could leave the monkey-patch in place, and check the stringified version of the function being passed in, and if it matches some criteria, then capture it.

Why I can not clearInterval in the following example?

I have the following issue. While the timer_mou starts counting, when the pause equals closeit it does not clear the interval.
What am I missing here?
function my_timer(pause){
console.log('function: '+pause);
var timer_mou = setInterval(function() {
console.log('counting');
}, 5000);
if (pause == 'closeit') {
clearInterval(timer_mou);
}
}
Just put the setInterval out of the pause function to define the variable timer_mou in the global scope, then when you call your function it will clear it correctly, instead of defining it on every call of the function, check the working example below.
Hope this helps.
var i = 0;
var timer;
start();
$('#pause').on('click',function(){
pause()
})
$('#restart').on('click',function(){
restart()
})
function pause(){
clearInterval(timer);
}
function restart(){
i=0;
pause()
start();
}
function start(){
timer = setInterval(function() {
i++;
console.log('Counting '+i);
},1000);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='pause'>Pause</button>
<button id='restart'>Restart</button>
You need to define timer_mou outside of the function. In your case you won't be able to clear the timer as you have lost reference to the timer and you create a new timer instance with every function call.
Try something like:
var timer_mou;
function start_timer() {
timer_mou = setInterval(function() {
console.log('counting');
}, 5000);
}
function stop_timer() {
clearInterval(timer_mou);
}
This is a very annoying problem that has to do with scope. When you declare the setInterval inside of your function, the only place you can clear it is inside of that iteration of the function. So,
my_timer("") //Starts a timer in the function
my_timer("closeit") //Starts a timer in the function, then stops it
//with the other timer running in the background
You can reduce the problem to the fact that your interval gets declared multiple times, and you can only stop it inside of the function. So, if you want the my_timer function to start the timer, but stop if you give it the parameter of "pauseit", you could implement something like this:
function my_timer(pause){
console.log('function: '+pause);
if(typeof timer_mou === "undefined"){ //If the interval already exists, don't start a new one
timer_mou = //Defines in global scope
setInterval(function() {
console.log('counting');
}, 5000);
}
if (pause == 'closeit') {
clearInterval(timer_mou);
}
}
So, in the new version of your function, it checks if the interval is defined, and if not, defines it in the global scope so you can remove it later.
Done on mobile, so that's my excuse for bad formatting and spelling errors.

Referencing Non-Global Variable for Timer JS

I have this function.
function changeFrame(){
var time = setInterval(start, 250);
}
and I want to stop it from firing in another function, but haven't been able to figure out how to do it.
Do you mean this?
function changeFrame(){
var time = setInterval(function() {
// Do stuff
}, 250);
}
Think it's in the comments.
Ok amended the fiddle to do what you want. I made time a global var. Call clearInterval in stop with the global var http://jsfiddle.net/QNWF4/3/
In order to call clearInterval you need to have the handle returned by setInterval. That means something will either be global to the page or global to a containing function in which your script resides.
function Timer()
{
var handle = null;
this.start = function (fn,interval) {
handle = setInterval(fn,interval);
};
this.stop = function ()
{
if (handle) { clearInterval(handle); handle = null; }
};
return this;
}

Javascript - Clearing the interval and setinterval scope

I have some AJAX that shows a progress bar using setInterval() to get the scripts current progress. My problem is that I cannot seem to kill it when progress has reached 100%. I am not sure if this has something to with scope, but my handler is global, so I can't figure out why it's not working. Here's what I have:
function showLog(){
document.getElementById('log').style.display = "block";
clearInterval(inth);
return false;
}
function startAjax(){
var inth = setInterval(function(){
if (window.XMLHttpRequest){ xmlhttpp=new XMLHttpRequest();}else{ xmlhttpp=new ActiveXObject("Microsoft.XMLHTTP"); }
xmlhttpp.onreadystatechange=function(){
if(xmlhttpp.readyState==4 && xmlhttpp.status==200){
document.getElementById("sbar").innerHTML=xmlhttpp.responseText;
}
}
xmlhttpp.open("POST","scrape.php",true);
xmlhttpp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
var sitelist = document.getElementById('website').value;
var par = "website="+sitelist;
xmlhttpp.send(par);
}, 5000);
return false;
}
Why is clearInterval not working? What am I doing wrong?
This is a scope issue, declare the var inth outside the function as a global variable. and use inth = setInterval(...) in the startAjax function.
As you said in your question, your handler is global. But the variable itself is not, so it can't be accessed outside the scope of the function.

Calling nested function from nested setInterval in an Object Namespace environment

I have this following piece of code:
var stats = {
....,
checkExistance :
function(url){
var newUrl = url.substring(0, url.lastIndexOf("/")) + "/asyncCheckChartExistance";
var xhrObj = stats.getXhr();
var poolInterval = setInterval("poll()", 100);
function poll(){
xhrObj.open("GET", newUrl, true);
xhrObj.send(null);
xhrObj.onreadystatechange = function(){
if(xhrObj.readyState === 4 && xhrObj.status === 200){
if (xhrObj.responseText.length === true){
console.log("Exists!");
clearInterval(poolInterval);
} else {
console.log("Not Yet!");
}
}
}
}
},
}
I created the stats namespace. In this namespace I'm trying to create a function which polls the server every second. I should access this function this way: stats.checkExistance(myUrl).
However it seems that the setInterval function is not able to see the poll() function. I know that this is normal behavior taking in consideration that these are nested inside another function.
If I were to write this in the Global namespace there would be no problem but I'm interested to make this work in this kind of namespace. Any ideas? Thanks!
when you pass a string to setInterval, it runs in the global scope, by default, where poll would not be defined since it only exists in the scope of the checkExistance function.
To fix the issue, pass an anonymous function to setInterval instead:
var poolInterval = setInterval(function () {
poll();
}, 100);
Passing an anonymous function is usually the best idea as it allows you to write any javascript expressions/statements for the interval instead of just calling one function.
When you pass a string to setInterval, that string is interpreted as global code, and since poll is not a global function, a reference error is thrown.
However, you can pass a function reference instead of a string, and since the poll function is available in the scope in which the setInterval invocation is made, you can just write this:
var poolInterval = setInterval( poll, 100 );
var stat = {
say: function(name){
function doit(){
console.log(name);
}
setInterval(doit, 1000);
}
};
stat.say("hi");​​​​​​​​​​​
A simple demo to show how. You will see "hi" every second.

Categories