Javascript setTimeout无法在for循环中工作

时间:2013-12-28 01:29:57

标签: javascript html html5 function settimeout

我必须每秒更改图像的来源。我有一个for循环,其中调用一个具有超时的函数。我在这里读取了stackOverflow,但它不起作用。可以请有人告诉我,我可以修复什么使其工作?我一直在努力解决这个问题,我想承认。感谢。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <script type="text/javascript">
        function changeImage(k) {
            setTimeout(function(){
              document.getElementById("img").src = k + ".png"; alert(k  );}, 1000);
        }
        function test() {
            for (var k = 1; k <= 3; k++) {
                changeImage(k);

            }
        }
    </script>
</head>

<body>
    <div id="main_img">
        <img id="img" src="http://placehold.it/110x110">
    </div>
    <input type="button" style="width: 200px" onclick="test()" />
</body>

6 个答案:

答案 0 :(得分:5)

在您的代码中,您可以立即设置所有超时。因此,如果你从现在开始设置 all 一秒钟,那么 all 从现在开始一秒钟。

您已经在索引k中传递,因此只需将时间参数乘以k

setTimeout(function(){
  document.getElementById("img").src = k + ".png";
  alert(k);
}, k * 1000);
// ^ added

答案 1 :(得分:2)

问题是你要创建一个间隔毫秒的实例。一秒钟后,它们也会分开几毫秒。你需要的是以彼此相隔的设定间隔执行它们。

您可以使用setInterval使用计时器,它以给定的间隔执行提供的功能。不要忘记杀掉计时器,否则它会永远运行。

次要优化

  • 您可以将元素缓存在变量中,这样您就不会经常访问DOM。

  • 另外,我会避开alert()。如果要调试,请在调试器中使用断点。如果您真的希望它像“类似警报”,请使用console.log并观看控制台。

  • setInterval相对于递归setTimeout的一个优点是,每次迭代不会产生多个计时器,而只会产生一个计时器。

以下是建议的解决方案:

var k = 0; 
var image = document.getElementById("img");
var interval = setInterval(function() {

   // Increment or clear when finished. Otherwise, you'll leave the timer running.
   if(k++ < 3) clearInterval(interval);
   image.src = k + ".png";

// Execute block every 1000ms (1 second)
},1000);

答案 2 :(得分:1)

您可以这样做,而不是使用循环:

var k = 0; 
var int = setInterval(function() {
   if (k <= 3) k++;
   else { clearInterval(int); }
   document.getElementById("img").src = k + ".png"; 
   alert(k);
}, 1000);

答案 3 :(得分:1)

问题

setTimeout不会停止程序执行,只会在1秒内为回调设置一个事件。这意味着如果你在for循环中设置了三个setTimeout,它们将在1秒后同时执行。

解决方案

您可以使用延迟递归,而不是使用for循环。

function changeImage(imageIndex) {
    document.getElementById("img").src = imageIndex + ".png"; 
    alert(imageIndex);
}

function myLoop( imageIndex ) {
    if( imageIndex >= 3 ) return;

    changeImage( imageIndex );

    setTimeut( function() { myLoop(imageIndex + 1) }, 1000 );
}

setTimeut( function() { myLoop(0) }, 1000 );

使用setInterval

的另一种解决方案
var interval = null;
var imageIndex = 0;

function changeImage() {
    document.getElementById("img").src = imageIndex + ".png"; 
    alert(imageIndex);

   imageIndex++;
   if( imageIndex === 3 ) clearInterval( interval );
}

interval = setInterval( changeImage , 1000);

使用不同的延迟

function changeImage(imageIndex) {
    document.getElementById("img").src = imageIndex + ".png"; 
    alert(imageIndex);
}

for( var i=0; i < 3; i++) {
    setTimeout( changeImage.bind(window, i), i * 1000 );
}

一个时髦的衬里(请不要使用它,永远!)

(function f(i) { setTimeout( changeImage(i) || f.bind(window, i = (i++)%3), 1000); })(0)

答案 4 :(得分:1)

我的建议是使用console.log()或alert()来帮助您进行调试 - 这将使得它变得更加明显正在发生的事情。例如,如果你在test或setTimeout函数中放置了console.log,你会发现所有三个图像都是同时添加的。

我建议的是声明你的“nextImage”函数,然后在该函数中定义你的setTimeout。这样它每秒都会自称。

另一个提示:我假设您希望这三个图像永远循环,所以我添加了一个常用的技巧和模数运算符(%)来完成此任务。

看看:

工作演示:http://jsfiddle.net/franksvalli/PL63J/2/

(function(){
    var numImages = 3,  // total count of images
        curImage  = 1,  // start with image 1
        $image    = document.getElementById("img"),
        imageBase = "http://placehold.it/110x11";

    function nextImage() {
        $image.src = imageBase + curImage;

        // increment by one, but loop back to 1 if the count exceeds numImages
        curImage = (curImage % numImages) + 1;

        // execute nextImage again in roughly 1 second
        window.setTimeout(nextImage, 1000);
    }

    // initializer.  Hook this into a click event if you need to
    nextImage();
})();

正如其他人所说,你可能想要使用setInterval,你可以通过一些调整来做:

(function(){
    var numImages = 3,  // total count of images
        curImage  = 1,  // start with image 1
        $image    = document.getElementById("img"),
        imageBase = "http://placehold.it/110x11";

    function nextImage() {
        $image.src = imageBase + curImage;

        // increment by one, but loop back to 1 if the count exceeds numImages
        curImage = (curImage % numImages) + 1;
    }

    // initializer.  Hook this into a click event if you need to
    nextImage(); // call function immediately without delay
    window.setInterval(nextImage, 1000);
})();

答案 5 :(得分:1)

为什么它不起作用?

因为Javascript总是通过引用传递变量。当您的代码在队列中等待时,变量已经更改。

我的解决方案:

创建一个数组并按照出现的顺序推送你想要执行的任何代码(直接放置变量的实际值),例如:

var launcher = [];
launcher.push('alert("First line of code with variable '+ x +'")');
launcher.push('alert("Second line of code with variable '+ y +'")');
launcher.push('alert("Third line of code with variable '+ z +'")');

使用setInterval而不是setTimeout来执行代码(您甚至可以动态更改延迟时间),例如。

var loop = launcher.length;
var i = 0;
var i1 = setInterval(function(){
    eval(launcher[count]);
    count++;
    if(i >= loop) {
        clearInterval(i1);
    }
}, 20);