Ryan Ryan - 1 month ago 10
Javascript Question

ClearInterval not working (but only sometimes) for sever api call

I have this function that is supposed to query the database every 4 seconds for any new content that may have been posted. I then take the return and refresh a feed with dynamic html made from whatever came back from the server. This all works great.

My problem is that as part of the html there is a options tray that they can press that will slide over part of the content and give them different options to do with that content, delete, copy, comment stuff like that. Well when they pop out the tray I want to clear the interval timer so that it does not refresh the html on in the feed (making the tray go away).

The other problem is that the user can have multiple trays open at the same time so I came up with this function to handle it all:

function setTimers(status)
{
var timerGetContent = null;
if(status == "login")
{
tray_count = 0;
timerGetContent = null;
timerGetContent = setInterval(getContent,4000);
alert("inside login");
}
else if(status == "negitive")
{
tray_count--;
if(tray_count == 0 && timerGetContent == null)
{
timerGetContent = setInterval(getRecentContent,4000);
alert("inside negitive");
}
}
else if(status == "positive")
{
tray_count++;
clearInterval(timerGetContent);
timerGetContent = null;
alert("inside positive")
}

}


So when the user presses the button to pop out the tray it calls setTimer and passes it positive before it does anything else, and then when they press the button to close the tray it calls setTimer and passes it negitive. I know the calls work and that its being passed the right parameters, I even know that its going into the right part of the function depending on what is pressed but there are times when the interval is just not cleared and it keeps firing no matter what I do. Been working on this for hours and am totally stumped.

Edit:
I have tried to have the var timerGetContent outside of the function as a global variable. This had the same behavior problems.

Edit2:
Function that calls the setTimers function:

function slide_out(event)
{
clicked_element = document.getElementById(event.srcElement.id);

var re_clicked = new RegExp(clicked_element.className, "g");
if(clicked_element.className == "options-bar slide-out")
{
BACKGROUND.setTimers("positive");
clicked_element.className = clicked_element.className.replace(re_clicked, '');
clicked_element.className += "options-bar slide-out open";

}
else
{
clicked_element.className = clicked_element.className.replace(re_clicked, '');
clicked_element.className += "options-bar slide-out";
BACKGROUND.setTimers("negitive");
}


One other thing, The setTimers function is in the background file of the extension while this function is in the popup.

Answer

The main issue here was scoping, as Femi suggested before. You must move var timerGetContent = null; outside the function declaration. You also had a logic error in the first condition, status == "login". You were setting the timerGetContent intervalID to null without clearing it first.

So, if you called setTimers("login"); after calling setTimers("negitive"); without calling setTimers("positive"); to first clear the interval, you would always have at least one interval going.

I replaced your function calls with console.log statements for testing:

var tray_count = 0;
var timerGetContent = null;
function setTimers(status) {
    if(status == "login") {
        tray_count = 0;
        // Setting the intervalID to null will NOT clear the interval
        // If we do not clear the interval, calling setTimers('login')
        // will create a new interval and make previous interval
        // "unclearable" every time it is called
        clearInterval(timerGetContent);
        timerGetContent = null;
        timerGetContent = setInterval(function() {
            console.log('login intervalling')
            },400);

    } else if(status == "negitive") {
        tray_count--;
        if(tray_count == 0 && timerGetContent == null) {
            timerGetContent = setInterval(function() {
                console.log('negitive intervalling')
            },400);
            alert("inside negitive");
        }
    } else if(status == "positive") {
        tray_count++;
        clearInterval(timerGetContent);
        // calling clearInterval does not actually unset the intervalID variable
        // so we need to set it to null manually
        timerGetContent = null;
        timerGetBlasts = null;
    }

}

Update 2014-07-14: Fixed a formatting typo --cbarrick