简体   繁体   English

一个for循环内的SetTimeout

[英]SetTimeout inside a for loop

I'm trying to write a script that changes the z-index of 3 images. 我正在尝试编写一个可更改3张图像的z-index的脚本。 Basically the script should target the current image and apply a higher z-index on the next image, like a sort of carousel but with a z-index rather then active class. 基本上,脚本应以当前图片为目标,并在下一张图片上应用更高的Z索引,就像轮播一样,但具有Z索引而不是活动类。 The challenge is to set the z-index after a specific interval. 挑战在于在特定间隔后设置z-index。 The problem is that the first image is displayed and then the last one. 问题在于显示的是第一个图像,然后是最后一个。 This is my code: 这是我的代码:

Html: HTML:

<div class="changingimages">
    <img src="#" data-time="3000" width="100%" class="alternateimage alternateimage1">
    <img src="#" data-time="2000" width="100%" class="alternateimage alternateimage2">
    <img src="#" data-time="4000" width="100%" class="alternateimage alternateimage3">
</div>

jQuery Script jQuery脚本

<script type="text/javascript">

jQuery(document).ready(function(){

    var changeImg = function(i, time, currentImg) {

        setTimeout(function(){

            jQuery(currentImg).next().css("z-index", i);

        }, time);
    };

    var numberOfChilds = jQuery(".changingimages").children().length;
    var currentIndexClass;
    var currentImg;
    var time;

    for (var i=1; i<=numberOfChilds; i++) {

            currentIndexClass = '.alternateimage' + i;
            currentImg = jQuery(currentIndexClass);
            time = jQuery(currentIndexClass).attr("data-time");

            changeImg(i, time, currentImg);

    }

});

I think there is some problem with the closure inside a loop, but not sure! 我认为循环中的闭包存在一些问题,但不确定!

It's a common misconception that setTimeout schedules events to run relative to previously queued events. 常见的误解是setTimeout将事件安排为相对于先前排队的事件运行。 It looks like you believe that, theoretically, the following: 从理论上讲,您似乎相信以下内容:

setTimeout(f, 100);
setTimeout(g, 100);
setTimeout(h, 100);

would result in a timeline like this: 会导致这样的时间轴:

0ms   Start
100ms Run f()
200ms Run g()
300ms Run h()

The reality is that the time option in setTimeout means "run this function after at least this much time has passed." 现实情况是setTimeout中的time选项表示“至少在经过这么多时间后运行此函数”。 Going off of the previous example, you would actually get something more like 从上一个示例来看,您实际上会得到更多类似的信息

0ms   Start
100ms Run f()
101ms Run g()
102ms Run h()

To space out your code correctly, keep adding to the timeout time rather than replacing it. 为了正确地分隔代码,请继续增加超时时间,而不是替换超时时间。

var time = 0;

for (var i = 1; i <= numberOfChilds; i++) {
  currentIndexClass = '.alternateimage' + i;
  currentImg = jQuery(currentIndexClass);

  // Add to the previous time
  time += parseInt(jQuery(currentIndexClass).attr("data-time"), 10);
  changeImg(i, time, currentImg);
}

Here is a fiddle implementing the use of timeout to achieve what you want. 这是一个小工具,实现了使用超时来实现所需的功能。

fiddle 小提琴

.textArea {
  position: absolute;
  height: 50px;
  width: 50px;
  display: block;
}

.box_a {
  background-color: blue;
}

.box_b {
  background-color: red;
}

.box_c {
  background-color: orange;
}

.active {
  z-index: 3;
}


<div class="textArea box_a active">a</div>
<div class="textArea box_b">b</div>
<div class="textArea box_c">c</div>

$(function(){
  var $elem = $('.textArea');

  timeout(0);

  function timeout(i){
    $($elem[i]).addClass('active');
    return setTimeout(function(){
      $elem.removeClass('active');
      i++;
      if(i >= $elem.length){
        i = 0
      }
      timeout(i);
    }, 1000)
  }
});

Note it does not use a for loop, because timeout is asynchronous and will not execute sequentially. 请注意,它不使用for循环,因为超时是异步的,不会顺序执行。 Each timeout will fire at the same time basically, then do their action based on the wait time. 基本上每个超时都会在同一时间触发,然后根据等待时间执行其操作。

The solution is to make a function that keeps track of the index, and when the last timeout has completed execution. 解决方案是创建一个跟踪索引以及上次超时何时完成执行的函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM