javascript 循环设置超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8202182/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 02:38:04  来源:igfitidea点击:

Looping setTimeout

javascriptjquery

提问by timkl

I'm currently trying to wrap my head around some JavaScript.

我目前正在尝试围绕一些 JavaScript 进行思考。

What I want is a text to be printed on the screen followed by a count to a given number, like so:

我想要的是要打印在屏幕上的文本,然后是给定数字的计数,如下所示:

"Test"

[1 sec. pause]

"1"

[1 sec. pause]

"2"

[1 sec. pause]

"3"

“测试”

[1秒。暂停]

“1”

[1秒。暂停]

“2”

[1秒。暂停]

“3”

This is my JS:

这是我的JS:

$(document).ready(function() {

    var initMessage = "Test";
    var numberCount = 4;    

function count(){

    writeNumber = $("#target");

    setTimeout(function(){
        writeNumber.html(initMessage);
    },1000);

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

    setTimeout(function(){
        writeNumber.html(i.toString());
    },1000+1000*i)};

};

 count();

});

This is my markup:

这是我的标记:

<span id="target"></span>

When I render the page, all I get is "Test" followed by "4".

当我呈现页面时,我得到的只是“测试”,然后是“4”。

I'm no JavaScript genius, so the solution could be fairly easy. Any hints on what is wrong is highly appreciated.

我不是 JavaScript 天才,所以解决方案可能相当简单。任何关于错误的提示都受到高度赞赏。

You can play around with my example here: http://jsfiddle.net/JSe3H/1/

你可以在这里玩我的例子:http: //jsfiddle.net/JSe3H/1/

回答by Andrew Whitaker

You have a variable scope problem. The counter (i) inside the loop is only scoped to the countfunction. By the time the loop has finished executing, is value is 4. This affects every setTimeoutfunction, which is why you only ever see "4".

你有一个可变范围的问题。i循环内的计数器 ( ) 仅作用于count函数。到循环执行完毕时,is 值为 4。这会影响每个setTimeout函数,这就是为什么您只会看到“4”。

I would rewrite it like this:

我会像这样重写它:

function createTimer(number, writeNumber) {
    setTimeout(function() {
        writeNumber.html(number.toString());
    }, 1000 + 1000 * number)
}

function count(initMessage, numberCount) {
    var writeNumber = $("#target");

    setTimeout(function() {
        writeNumber.html(initMessage);
    }, 1000);

    for (var i = 1; i < numberCount; i++) {
        createTimer(i, writeNumber);
    }
}

$(document).ready(function() {

    var initMessage = "Test";
    var numberCount = 4;


    count(initMessage, numberCount);

});

The createTimerfunction ensures that the variable inside the loop is "captured" with the new scope that createTimerprovides.

createTimer函数确保循环内的变量被提供的新范围“捕获” createTimer

Updated Example:http://jsfiddle.net/3wZEG/

更新示例:http : //jsfiddle.net/3wZEG/

Also check out these related questions:

另请查看以下相关问题:

回答by dxh

In your example, you're saying "2, 3, 4 and 5 seconds from now, respectively, write the value of i". Your for-loop will have passed all iterations, and set the value of ito 4, long before the first two seconds have passed.

在您的示例中,您分别是说“从现在起 2、3、4 和 5 秒,分别写入“的值i。您的 for 循环将通过所有迭代,并将 的值设置i为 4,早在前两秒过去之前。

You need to create a closure in which the value of what you're trying to write is preserved. Something like this:

您需要创建一个闭包,在其中保留您尝试编写的内容的值。像这样的东西:

for(var i = 1; i < numberCount; i++) {
    setTimeout((function(x) {
        return function() {
            writeNumber.html(x.toString());
        }
    })(i),1000+1000*i)};
}

Another method entirely would be something like this:

另一种方法完全是这样的:

var i = 0;
var numberCount = 4;

// repeat this every 1000 ms
var counter = window.setInterval(function() {

   writeNumber.html( (++i).toString() );

   // when i = 4, stop repeating
   if(i == numberCount)
       window.clearInterval(counter);

}, 1000);

回答by Sudhir Bastakoti

Hope this helps:

希望这可以帮助:

var c=0;
var t;
var timer_is_on=0;

function timedCount()
{
document.getElementById('target').value=c;
c=c+1;
t=setTimeout("timedCount()",1000);
}

function doTimer()
{
if (!timer_is_on)
  {
  timer_is_on=1;
  timedCount();
  }
}