1

可能重复:
如何在 for...循环中使用 setTimeout 使用 for 循环
调用 setTimeout

对我来说,setTimeout函数在 for 循环中不起作用。它在执行所有 for 循环语句后执行。

setTimeout如果在javascript中使用函数,我将面临这个范围问题。

这是我的代码片段..

 ... moves[] is an array ..

 for(i=0;i<noOfMoves;i++) {

        playerName = moves[i].playerName;
        timeDiff = moves[i].timeDiff;
        console.log("Inside for loop"+ playerName);

        setTimeout(function(){
             console.log("Inside set time out :"+playerName);
        },timeDiff);
 ....
 ....
}

但它笨拙地打印出以下输出......

 Inside for loopplayer1
 Inside for loopplayer2
 Inside for loopplayer3
 Inside for loopplayer4
 .... (noOfMoeves times .. )
 Inside set time outplayer1
 Inside set time outplayer1
 Inside set time outplayer1
 Inside set time outplayer1

编辑 :

我想要以下方式的o/p

我期望代码逐行运行..Inside for loop首先打印“”控制台日志,然后等待“ timeDiff”期间,然后打印“ Inside settimeout”功能控制台日志..我该怎么做?——</p>

 Inside for loopplayer1
 Inside set time outplayer1 // (after waiting for timeDiff time)
 Inside for loopplayer2
 Inside set time outplayer2  // (after waiting for timeDiff time)
 ......
 ......

此外, playerName 变量在每个 settimeout 控制台日志语句中都获得相同的值吗?

4

3 回答 3

2

这不完全是由于闭包,这是因为 javascript 是单线程的,并且在 javascript 有空闲时间执行之前不会发生设置 Timeout。for 循环总是在 setTimeout 执行它的代码之前完成。

要解决此问题,请将所有内容放入 setInterval 中,如下所示:

var moves = [{playerName:'Test'},{playerName:'Terry'}, {playerName:'sdfsdf'}];
var currIdx = 0;
var intervalId = window.setInterval(function () {
    var playerName = moves[currIdx].playerName;
    console.log("Inside for loop"+ playerName);
    (function(name) {
        setTimeout(function(){
             console.log("Inside set time out :"+name);
        },0);
    })(playerName);
    currIdx++;
    if(currIdx >= moves.length)
        window.clearTimeout(intervalId);        
}, 10);

请参阅小提琴的示例 - http://jsfiddle.net/uTyVw/2/

于 2012-06-14T16:23:00.790 回答
1

这是因为关闭。像这样更改您的代码:

for(i=0;i<noOfMoves;i++) {
    playerName = moves[i].playerName;
    console.log("Inside for loop"+ playerName);
    (function(name) {
        setTimeout(function(){
             console.log("Inside set time out :"+name);
        },timeDiff);
    })(playerName);
}

你可以在这里了解更多关于闭包的信息。

更新代码:

var moves = [
    {playerName: '1'},
    {playerName: '2'},
    {playerName: '3'},
    {playerName: '4'}
];
var timeDiff = 1000;
var currentMove = 0;

var processNextMove = function() {
    var move = moves[currentMove];
    console.log('Inside for loop: ' + move.playerName);
    currentMove++;
    window.setTimeout(function() {
        console.log('Inside set time out: ' + move.playerName);
        if(currentMove != moves.length) {
            processNextMove(); 
        }
    }, timeDiff);
};

processNextMove();
于 2012-06-14T16:18:01.063 回答
0

一旦迭代和延迟完成,您似乎想要进入下一个项目。这是一个可能对您有所帮助的步进器。

// Generic stepper. On step will move to next item and
// run custom stepping function. If at the end will return 0.
function Stepper(stepfunc, items) {
    this.items = items;
    this.index = -1;
    this.stepfunc = stepfunc;
}

Stepper.prototype.start = function() {
    this.index = -1;
    this.step();
}

Stepper.prototype.step = function() {
    this.index++; // move to the next item

    // Stop when we reach the end.
    if (this.items.length <= this.index) {
        return 0;
    }

        /* Do something now. */
        var item = this.items[this.index];
        this.stepfunc(item);

        return 1;
}

// Custom step function.
function myStep(item) {
    // Do this now.
    console.log(item.n);

    // Get a reference to the stepper.
    var s = this;

    // Do this later.
    setTimeout(function(){
        console.log(item.n + ' after ' + item.t);
        var status = s.step();
        console.log(status);
    }, item.t);
}

var items = [{n: 'A', t: 500}, {n: 'B', t: 600}, {n: 'C', t: 1000}];
var s = new Stepper(myStep, items);
s.start();
于 2012-06-14T19:31:57.507 回答