我正在尝试按时间间隔分隔函数调用。下面的代码当前采用每个函数调用的最后一项。
当前代码打印:itemThree,itemThree,itemThree - 每个分隔十秒
打印所需的代码:itemOne,itemTwo,itemThree - 每个分隔10秒
//Declare variables
var itemList = ["itemOne", "itemTwo", "itemThree"];
var timerInterval = 0;
//Loop through the itemList and build a list of functions calls
//Each function call will be lined up with a 10 second gap
for(index = 0; index < itemList.length; index++) {
var item = itemList[index];
setTimeout(function() { doSomethingWithItem(item); }, timerInterval);
timerInterval = timerInterval + 10000;
}
//Print passed in item
var doSomethingWithItem = function(item) {
console.log(item);
}
我正在尝试列出定时器延迟函数调用。我如何更改上述代码,还是有更好的解决方案?谢谢你的帮助。
答案 0 :(得分:2)
JavaScript通过引用传递值,并且在超时触发时,index
将达到其最大值,因此将始终显示“itemThree”。要解决此问题,您需要为循环变量创建另一个作用域,以便它不会被外部作用域更改。
//Loop through the itemList and build a list of functions calls
//Each function call will be lined up with a 10 second gap
for(index = 0; index < itemList.length; index++) {
// creating new scope for index to live in
(function(num) {
var item = itemList[num];
setTimeout(function() { doSomethingWithItem(item); }, timerInterval);
timerInterval = timerInterval + 10000;
})(index);
}
答案 1 :(得分:2)
我在这种情况下使用的方法是在伪递归循环中使用立即调用的函数表达式,一次一个地从列表中提取元素:
//Declare variables
var itemList = ["itemOne", "itemTwo", "itemThree"];
var timerInterval = 10000;
(function loop() {
var item = itemList.shift();
if (item) {
setTimeout(function() {
doSomethingWithItem(item);
loop()
}, timerInterval);
}
})();
//Print passed in item
var doSomethingWithItem = function(item) {
console.log(item);
}
如果没有for
循环,则可以避免在每次回调期间item
变量的最后一个分配值的问题。
使用setTimeout
的伪递归使用,您还可以避免一次排队多个计时器。我将此用法命名为伪递归,因为尽管可能看起来loop
正在调用自身,但实际上setTimeout
调用只是将回调添加到要从中触发的函数队列浏览器的事件处理循环。