nines
nines

Reputation: 521

suspend setInterval

I use setInterval to run a function (doing AJAX stuff) every few seconds. However I also have an other function also calling it.

setInterval(myFunc(), 5000);
function buttonClick() {
  // do some stuff
  myFunc();
}

Most of the time it works, however sometimes this function gets called twice at the same time resulting in receiving exactly the same result twice, something I don't want.

I think I have to use clearTimeout:

var interval = setInterval(myFunc(), 5000);
function buttonClick() {
  clearTImeout(interval);
  // do some stuff
  myFunc();
  interval = setInterval(myFunc(), 5000);
}

However this causes the function to halt. Since it gets called from an other function some code never gets executed. How can I prevent this?

Upvotes: 1

Views: 2718

Answers (3)

Jan
Jan

Reputation: 8141

Unless myFunc returns a function I would do this (also use clearInterval in stead of clearTimeout):

var interval = setInterval(myFunc, 5000);
function buttonClick() {
  clearInterval(interval);
  // do some stuff
  myFunc();
  interval = setInterval(myFunc, 5000);
}

setInterval expects a function in its argument. You call a function by using myFunc(). so whatever is returned by myFunc was passed to setInterval which is probably not what you want.

Upvotes: 0

Brad Christie
Brad Christie

Reputation: 101614

I realize there's a couple of solutions already, but thought I'd show one that has a tad more than just "do this". I tend to learn by example, and thought I would extend the same practice. That being said, the demo is here but I'll try to explain as well.

// Here we assign the function to a variable that we can use as an argument to the
// setInterval method.
var work = function(){
    // performing a very simple action for the sake of demo
    $('#log').append('Executed.<br />');
};

// this is a variable that is essentially used to track if the interval is or is
// not already running. Before we start it, we check it. Before we end it, we also
// check it. Let's start off with it started though
var worker = setInterval(work, 5000);

// bind to the start button
$('#start').click(function(){
    // Test: is the worker already running?
    if (worker)
        // Yes it is, don't try to call it again
        $('#warn').text('Timer already running!');
    else{
        // no it's not, let's start it up using that function variable we declared
        // earlier
        worker = setInterval(work,3000);
        $('#warn').text('Started!');
    }
});

// bind to the stop button
$('#stop').click(function(){
    // test: is the worker running?
    if (!worker)
        // no, so we can't stop it
        $('#warn').text('Timer not running!');
    else{
        // yes it's working. Let's stop it and clear the variable.
        clearInterval(worker);
        worker = null;
        $('#warn').text('Stopped.');
    }
});

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074385

however sometimes this function gets called twice at the same time resulting in receiving exactly the same result twice, something I don't want.

JavaScript on browsers is single-threaded (barring using the new web workers stuff, but that wouldn't apply here anyway). Your function will never get called while it's running. (But more below.)

In your various code quotes, you're calling myFunc where you mean to just be referring to it. E.g.:

var interval = setInterval(myFunc(), 5000);

should be

var interval = setInterval(myFunc, 5000);
//                               ^--- No parentheses

Your code cancelling the timeout will work if you correct that:

var interval = setInterval(myFunc, 5000);
function buttonClick() {
  clearTImeout(interval);
  // do some stuff
  myFunc();
  interval = setInterval(myFunc, 5000);
}

But there's no reason to do that, myFunc cannot get called while it's running anyway.

If myFunc is triggering something that will complete asynchronously (an ajax call, for instance), the above won't help (for the simple reason that myFunc will start the process and then return; the process will complete separately). In that situation, your best bet is to have myFunc schedule its next call itself:

function myFunc() {
    // Do my work...

    // Schedule my next run
    setTimeout(myFunc, 5000);
}

...and not use setInterval at all.

Upvotes: 2

Related Questions