Alan Coromano
Alan Coromano

Reputation: 26008

How can I delay a loop depending on a condition?

I want to create a delay in a loop depending on a condition. Say, I have this:

var maxLoops = 50;
var counter = 0;

(function next() {
    if (counter++ >= maxLoops) {
      return;
    }

    setTimeout(function() {
        console.log(counter);
        next();
    }, 100);
})();

Is there any way to pause the process for 2 seconds only when the counter is equal to 10, 20 or 30? So it should print:

 1....10 
 (delay for a custom period of time)
 11....20
 (delay for a custom period of time)
 21....30
 (delay for a custom period of time)
 31...50

The bottom line is, I don't want to delay at all when the counter isn't equal to 10, 20, 30.

Upvotes: 0

Views: 73

Answers (2)

jfriend00
jfriend00

Reputation: 707218

You can just use the setTimeout() with a different timing based on your counter:

var maxLoops = 50;
var counter = 0;

(function next() {
    if (counter++ >= maxLoops) {
      return;
    }
    var delay = 0;
    // on multiples of 10, use a longer counter
    if (counter % 10 === 0) {
        delay = 2000;
    }
    setTimeout(function() {
        console.log(counter);
        next();
    }, delay);
})();

Or, you could skip the setTimeout() completely when you don't need the delay.

var maxLoops = 50;
var counter = 0;

(function next() {
    if (counter++ >= maxLoops) {
      return;
    }
    // on multiples of 10, use a longer counter
    if (counter % 10 === 0) {
        setTimeout(function() {
            console.log(counter);
            next();
        }, 2000);
    } else {
        console.log(counter);
        next();
    }
})();

Or, rather than recursion, you can just use a while loop as in this working snippet:

var maxLoops = 50;
var counter = 0;

(function next() {
    // while we haven't hit maxLoops and while not a multiple of 10
    while (counter < maxLoops && counter % 10 !== 0 && counter !== 0) {
        log(counter);
        ++counter;
    }
    if (counter < maxLoops) {
        setTimeout(function() {
            log(counter);
            ++counter;
            next();
        }, 1000);
    }
})();

function log(x) {
    var div = document.createElement("span");
    div.innerHTML = x + " ";
    document.body.appendChild(div);
}

Upvotes: 1

Lo&#239;c Faure-Lacroix
Lo&#239;c Faure-Lacroix

Reputation: 13600

Sure you can do that just change the timeout when you have a multiple of 10.

var maxLoops = 50;
var counter = 0;

(function next() {
    counter += 1
    var timeout_duration = counter % 10 == 0 ? 2000 : 0;

    if (counter >= maxLoops) {
      return;
    }

    setTimeout(function() {
        console.log(counter);
        next();
    }, timeout_duration);
})();

That said, there need some few improvments because maxLoops and counter are defined on the global scope. Make it a function.

function loop (maxLoops, start) {
    var counter = start || 0;

    (function next() {
        counter += 1
        var timeout_duration = counter % 10 == 0 ? 2000 : 100;

        if (counter >= maxLoops) {
          return;
        }

        setTimeout(function() {
            console.log(counter);
            next();
        }, timeout_duration);
    })();
}

loop(50);

If you don't want to call next when counter isn't a multiple of 10, then you can add a usual loop in between the calls.

function loop (maxLoops, start) {
    var counter = start || 0;
    var timeout_duration = 2000;

    (function next() {
        while(counter < maxLoops && counter % 10 != 0) {
          counter += 1
        }

        if (counter >= maxLoops) {
          return;
        }

        setTimeout(function() {
            console.log(counter);
            next();
        }, timeout_duration);
    })();
}

loop(50);

That said, keep in mind that a setTimeout of 2000 doesn't mean exactly 2 seconds, but not less than 2 seconds. If somehwere, there is a loop that breaks the thread, the setTimeout could be never called as Javascript is single threaded and there is no fact that the function will be called after 2 seconds. If you're planning to use setTimeout to measure something within time, you might have to plan something else that will include the Date object for timings.

Upvotes: 5

Related Questions