可能重复:
How to Use setTimeout in a for…loop
calling setTimeout with a for loop
对我来说,setTimeout
函数在for循环中不起作用。它会在所有for循环语句执行后执行。
我在javascript中使用setTimeout
函数时遇到此范围问题。
这是我的代码段..
... 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
”函数控制台日志..我该怎么做? -
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控制台日志语句中获得相同的值?
答案 0 :(得分:2)
这不完全是由于闭包,这是因为javascript是单线程的,并且设置Timeout不会发生,直到javascript有空闲时间执行。 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/
答案 1 :(得分: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);
}
您可以了解有关闭包的更多信息here。
更新代码:
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();
答案 2 :(得分: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();