最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - get SetTimeout to finish before continuing loop - Stack Overflow

programmeradmin5浏览0评论

I'm trying to get a row of letters to light up one by one using Javascript/jquery. I created an array using span elements and am looping over each letter to first change its color red and then back to black again. The problem is that the $.each loop function doesn't wait for setTimeout to finish...it loops over all of them instantly making them all turn red instantly instead of one by one. Any ideas how to fix this? Here is my code:

JSFiddle: /

var array = $(".one");

var doIt = function () {
    $.each(array, function(index, value){
            array.eq(index).css('color','red');
        setTimeout(function(){
            array.eq(index).css('color','black');                                
        }, 500);
    });

};

doIt();
P {
    color:black;
}
<script src=".11.1/jquery.min.js"></script>
<p>
    <span class="one">H</span><span class="one">e</span><span class="one"></span><span class="one">l</span><span class="one">l</span><span class="one"></span><span class="one">o</span><span class="one"> M</span><span class="one"></span><span class="one">y </span><span class="one">N</span><span class="one"></span><span class="one">a</span>
</p>

I'm trying to get a row of letters to light up one by one using Javascript/jquery. I created an array using span elements and am looping over each letter to first change its color red and then back to black again. The problem is that the $.each loop function doesn't wait for setTimeout to finish...it loops over all of them instantly making them all turn red instantly instead of one by one. Any ideas how to fix this? Here is my code:

JSFiddle: http://jsfiddle/john23/8chu18k9/

var array = $(".one");

var doIt = function () {
    $.each(array, function(index, value){
            array.eq(index).css('color','red');
        setTimeout(function(){
            array.eq(index).css('color','black');                                
        }, 500);
    });

};

doIt();
P {
    color:black;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
    <span class="one">H</span><span class="one">e</span><span class="one"></span><span class="one">l</span><span class="one">l</span><span class="one"></span><span class="one">o</span><span class="one"> M</span><span class="one"></span><span class="one">y </span><span class="one">N</span><span class="one"></span><span class="one">a</span>
</p>

Share Improve this question edited Jan 26, 2015 at 17:57 taesu 4,5805 gold badges26 silver badges41 bronze badges asked Jan 26, 2015 at 17:26 John23John23 1992 gold badges6 silver badges15 bronze badges 1
  • 1 you should set the timeout properly while doing so.. try to set it like this setTimeout(....., 500 * (index +1)); ............ The problem in existing logic is that it is setting timeout for all characters at same time in loop so even though it is technically setting it for each character separetly, but effect is not recognized due to fast execution. – K D Commented Jan 26, 2015 at 17:33
Add a ment  | 

3 Answers 3

Reset to default 2

setTimeout is asynchronous. It will return control back to the calling context immediately, so this code will not work as expected. I suggest using setInterval instead, which runs the same function repeatedly, at the given interval:

var array = $('.one');
var currentIndex = 0;
var intervalId = setInterval(function(){
  array[currentIndex].css('color','black');
  currentIndex++;
  // We've reached the end of the array, stop calling this function
  if (currentIndex == array.length) clearInterval(intervalId);
}, 500);

To clarify a little: setInterval will return an ID. You can then pass that ID to the function clearInterval to stop the invocation of the function.

This is what you want: http://jsfiddle/8chu18k9/1/

var array = $(".one");
var i = 0;

var doIt = function () {

    setTimeout(loopIt, 500)       
};

var loopIt = function() {

    if(i < array.length) {
        console.log("inner loop")
          array.eq(i).css('color','red');   
        if(i > 0) {
            array.eq(i-1).css('color','');               
        }        
        i++
        setTimeout(loopIt, 500)
    }    
}


doIt();

If you don't want the letters to go back to black, delete:

 if(i > 0) {
     array.eq(i-1).css('color','');               
 }        

In case you want the setTimeout solution. Here it is.

Html:

<p>
  <span class="one">H</span>
  <span class="one">e</span>
  <span class="one">l</span>
  <span class="one">l</span>
  <span class="one">o</span>
  <span class="one"> M</span>
  <span class="one">y </span>
  <span class="one">N</span>
  <span class="one">a</span>
</p>
<script src="//code.jquery./jquery-1.11.2.min.js"></script>

Css:

P {
    color:black;
}

Js:

var delayBase = 10;
var baseDuration = 500; //Time at which each span stays red for

$(document).ready(function(){
  $(".one").each(function(){
    flash($(this), delayBase, baseDuration);
    delayBase+=1000;
  });
});

function flash($element, delay, flashDuration){ 
  //set red
  setTimeout(function(){
    $element.css('color', 'red');
  }, delay );
  //set black
  setTimeout(function(){
    $element.css('color', 'black');
  }, (delay+flashDuration) );
}

codepen example: http://codepen.io/anon/pen/zxzeKE

发布评论

评论列表(0)

  1. 暂无评论