0

I'm confused about how to use the setTimeout function within a for loop. What I'm trying to do is highlight divs one at a time based on an array. Here's my code:

for (i = 0; i < strArray.length; i++) {
  doSetTimeout(i, colors, strArray);
}

and then the function, doSetTimeout:

function doSetTimeout(i, colors, strArray) {
  $("use." + strArray[i]).css("fill", colors[Math.floor((Math.random() * colors.length) + 1)]);
  setTimeout(function() {
    $("use").css("fill", "#333333");
  }, 1000);
}

Based on this thread, I thought having a separate function to do the color changing would solve the problem, but I'm still having an issue where all of the divs flash at the same time. Anyone know what the issue might be? And is there another, preferable way to do this?

5
  • 4
    Because you did not change the duration... }, 1000 * i); will do... Commented Aug 25, 2016 at 17:48
  • 1
    @Rayon, changing the duration alone does not prevent that the first fill statement is executed at the same time for all elements. Commented Aug 25, 2016 at 17:55
  • @trincot – I did not notice that... Good one ;) Commented Aug 25, 2016 at 17:59
  • Note that the "+1" inside the color array index is a bug. Indices start at 0 and go to length-1. You should better round the random*length. Commented Aug 25, 2016 at 18:30
  • Did any of the answers suit your needs? Could you accept one or leave a comment? Commented Sep 13, 2016 at 17:51

3 Answers 3

4

You could do it like this:

(function doSetTimeout(i, colors, strArray) {
  if (i >= strArray.length) return; // nothing more to do
  $("use." + strArray[i]).css("fill", colors[Math.floor((Math.random() * colors.length) + 1)]);
  setTimeout(function() {
    $("use").css("fill", "#333333");
    // call the function recursively
    doSetTimeout(i+1, colors, strArray);
  }, 1000);
})(0, colors, strArray); // Execute immediately for index 0

This creates a function and executes it immediately for the first element in the array.

All other calls are only done when the previous timeout event has been triggered, which will ensure a sequential processing.

The whole thing ends when all elements have been processed, since in the last call to doSetTimeout no new timeout is scheduled.

Sign up to request clarification or add additional context in comments.

Comments

0

You can do it like this:

function doSetTimeout(i, colors, strArray) {
  if(i >= strArray.length) return;  

  $("use." + strArray[i]).css("fill", colors[Math.floor((Math.random() * colors.length) + 1)]);
  setTimeout(function() {
    $("use").css("fill", "#333333");

    doSetTimeout(i + 1, colors, strArray);
  }, 1000);
}

doSetTimeout(0, colors, strArray);

Comments

0

Why not to use setInterval instead?

    var i = 0;        
    var intervalID = setInterval(function() {

        if (i < strArray.length) {
             $("use").css("fill", "#333333");
             $("use." + strArray[i]).css("fill", colors[Math.floor((Math.random() * colors.length) + 1)]);
             clearInterval(intervalID)
        }
        i++;
    }, 1000);

2 Comments

Starting i at 0 and incrementing after the condition reads easier IMHO
True. Fixed it. Thanks

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.