【问题标题】:setTimeout in a loop, it behaves different than expectedsetTimeout 在循环中,它的行为与预期不同
【发布时间】:2015-02-11 17:06:11
【问题描述】:

所以我知道 setTimeout() 函数可以在一定时间后触发传入的函数,但在循环中似乎表现不同。例如:

for (var i = 0; i < 5; i++) {
  setTimeout(console.log(i + ', time is: ' + new Date()), 1000);
}

console.log() 似乎同时打印出所有数字。我不理解为什么。你们中的一些人能解释一下为什么setTimeout() 在这个循环中不起作用吗?

【问题讨论】:

  • setTimeout 不是暂停,它从现在开始设置超时并继续。这样做的方法是一个递归函数,它记录自己并使用 settimeout 再次调用自己,向传递的参数添加一个(并记住在满足条件时停止递归。
  • 你目前写这个的方式相当于做console.log(i + ', time is: ' + new Date()); setTimeout(undefined, 1000);

标签: javascript settimeout


【解决方案1】:

您没有将console.log 传递给setTimeout,而是立即调用它。

另外,您需要将i 放入闭包中,否则所有调用都会记录5

试试这个:

function makelogger(i) {
    return function () {
        console.log(i + ', time is: ' + new Date());
    }
}

for (var i = 0; i < 5; i++) {
    setTimeout(makelogger(i), 1000); // or i*1000
}

【讨论】:

  • fwiw 它同时在 chrome 和 firefox 中打印 5 条日志消息。
  • 如果您希望它每秒记录一个,请将 1000 替换为 i*1000,正如我在该评论中指出的那样。
【解决方案2】:

如果你想每秒都执行控制台功能,你需要做一些不同的事情。

    for (var i = 1; i <= 5; i++) 
    {
      setTimeout( function() 
      {
        document.write(new Date() + "<br />");
      }, (i * 1000));
    }

这将以 1 秒为间隔显示时间,共 5 次。

【讨论】:

  • 打印:5,时间是:2014 年 12 月 12 日星期五 17:24:52 GMT-0500 (EST) 5,时间是:2014 年 12 月 12 日星期五 17:24:52 GMT-0500 (EST) ) 5、时间为:Fri Dec 12 2014 17:24:52 GMT-0500 (EST) 5、时间为:Fri Dec 12 17:24:52 GMT-0500 (EST) 5、时间为:Fri Dec 12 2014 17:24:52 GMT-0500 (EST)
【解决方案3】:

您可以链接您的 setTimeouts:

  setTimeout(function() {
    console.log(1 + ', time is: ' + new Date())
    setTimeout(function() {
        console.log(2 + ', time is: ' + new Date())
    }, 1000);
  }, 1000);

或者你可以使用一个函数让它变得更好:

times = 5;
timeout(times);

function timeout(times) {
    setTimeout(function(){
        console.log(times + ', time is: ' + new Date())
        if(times > 1) {
            setTimeout(timeout(times-1), 1000);
        }
    },1000) 
}

【讨论】:

  • 内部setTimeout的目的是什么?你已经在做一个 setTimeout 了。 (并且您错误地将timeout 传递给它。)
【解决方案4】:

在您的setTimeout 中,第一个参数应该返回一个稍后将执行的函数。因此,您需要一个将是函数调用的表达式,而不是函数调用本身。

试一试,举个粗略的例子:(ttl 是活下去的试验 :)

function makelogger(ttl) {
    var msg = ttl + ', time is: ' + new Date();
    console.log(msg);

    if ( ttl > 0 ) {
      setTimeout(function(){return makelogger(ttl-1)}, 1000); 
    }
}
makelogger(5)

Here 是完整的 MDN 描述

【讨论】:

    【解决方案5】:

    解决问题的方法是将函数包装到闭包中:

    for (var i = 1; i <= 5; i++) 
    {  
        (function(j)
        {
            setTimeout(function() 
            {
                document.write(j + " - " + new Date() + "<br />");
            }, (j * 1000));
        })(i);      
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-11
      • 2021-09-12
      • 1970-01-01
      • 2015-07-18
      • 1970-01-01
      • 2014-12-12
      • 1970-01-01
      相关资源
      最近更新 更多