【问题标题】:Calling setTimeout function within a loop在循环中调用 setTimeout 函数
【发布时间】:2012-03-10 05:47:56
【问题描述】:

我是 javascript 新手,正在尝试使用 setTimeout 从 for 循环中调用函数。循环针对 nodeList 的每个成员执行。

我发现我用 setTimeout 调用的函数实际上只是在循环的最后一次迭代期间执行。在下面的示例中,我想对 setTimeout 进行三个单独的调用,但我发现前两个调用被忽略了。

function moveants(e, stepdistance) {

    . . . . .

    for(var i = 0; i < 3; i++)
    {
        var nextAnt = antgroup.childNodes[i]
        nextAnt.count = 0;
        nextAnt.member = i;
        setTimeout(function () { takeStep(nextAnt, mouseclickX, mouseclickY, 10) }, 0);
    }
}

function takeStep(ant, destX, destY, stepDistance) {

    . . . .

    . . . .

    if( condition )
    {
        return;
    }
    else
    {
        takeStep(ant, destX, destY, stepDistance);
    }
}

我看到other posts 描述了多次调用 setTimeout。令人惊讶的是(对我来说),如果我像这样简单地将它们从 for 循环中取出,多个调用将起作用。

    setTimeout(function () { takeStep(antgroup.childNodes[0], 
         mouseclickX, mouseclickY, 10) }, 10);
    setTimeout(function () { takeStep(antgroup.childNodes[1], 
         mouseclickX, mouseclickY, 10) }, 10);
    setTimeout(function () { takeStep(antgroup.childNodes[2], 
         mouseclickX, mouseclickY, 10) }, 10);

我只是不明白为什么在 for 循环中调用它们和在循环之外调用它们之间存在差异。

在每种情况下,我都从 setInterval 调用中获得了有效的返回值。只是只有 for 循环的最后一次迭代,函数才会真正执行。

提前感谢您的帮助。

【问题讨论】:

  • 正如 Dark Slipstream 所说:你有 0 延迟超时 尝试延迟,例如 setTimeout(function () { takeStep(nextAnt, mouseclickX, mouseclickY, 10) }, 10);
  • 我很抱歉。我也在循环内设置了 10 的延迟,但我不小心删除了帖子中的时间参数。

标签: javascript for-loop settimeout


【解决方案1】:

nextAnt 将在每个循环中被覆盖,因此 takeStep() 将被调用 3 次,但始终使用相同的参数。

你可以试试这个:

(function(a,b,c){
     setTimeout(function(){
                           takeStep(a,b,c,10)}, 0);
      })(nextAnt, mouseclickX, mouseclickY);

【讨论】:

  • 哇。你很厉害。这行得通。这是 闭包 的事情吗?我会认为传递给 setTimeout 每次迭代的参数本质上是私有的,但显然情况并非如此。我想我现在的问题是为什么当我在 for 循环之外进行调用时它们是私有的?我将不得不考虑一段时间。是我对 for 循环中变量范围的理解不正确还是我对 setTimeout 工作原理的理解?非常感谢。
  • 噢……我想我现在明白了!因此,所有三个 setTimeout 调用中的 i 实际上在 for 循环迭代的整个过程中仍然“在范围内”。我发现这个other post 讨论了同样的问题。荒野。奇怪的是,变量范围可以通过一层封闭而不是两层向下延伸。总之,很爽。再次感谢!
【解决方案2】:

如果您没有设置延迟,那么为什么还要麻烦 setTimeout?

在循环中,您的延迟设置为 0,在您使用的循环外设置为 10。此外,在循环外,您已将值分配给 count 和 member,但不在循环外?

试试这个:

function moveants(e, stepdistance)
{
    for (var i = 0; i < 3; i++)
    {
        setTimeout("takeStep(antgroup.childNodes[i], mouseclickX, mouseclickY, 10)", 0);
    }
}

或者这个:

function moveants(e, stepdistance)
{
    for (var i = 0; i < 3; i++)
    {
        takeStep(antgroup.childNodes[i], mouseclickX, mouseclickY, 10);
    }
}

【讨论】:

  • 当我尝试将整个 takeStep 函数调用作为字符串或者如果我在匿名函数中使用 nodeList[] 成员时,解释器会告诉我第一个参数在其中未定义takeStep 函数。我认为这是一个变量范围问题。
  • 我完全使用 setTimeout 的原因(根据您在“或这个”之后的代码)是为了尝试模拟所有蚂蚁同时移动(而不是连续移动)。这就是我从 for 循环中取出 setTimeout 调用时得到的行为。
  • 我很抱歉。我在循环内也设置了10的延迟,但我不小心删除了帖子中的time参数。 nextAnt.count 属性在 takeStep 函数中用作 condition 的一部分,并且实际上在两者中都设置了(再次,抱歉!)。 nextAnt.member 仅用于调试循环迭代。
  • 第一个不行;将字符串传递给setTimeout() 通常不是一个好主意
猜你喜欢
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
  • 2021-03-06
  • 1970-01-01
相关资源
最近更新 更多