0

我正在尝试制作一个按时间间隔分隔的函数调用列表。下面的代码当前采用每个函数调用的最后一项。

当前代码打印:itemThree、itemThree、itemThree - 每个相隔十秒

所需的代码打印:itemOne、itemTwo、itemThree - 每个相隔十秒

//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);
}

我正在尝试列出计时器延迟函数调用。我需要如何更改上述代码,还是有更好的解决方案?感谢您的帮助。

4

2 回答 2

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);
}
于 2013-07-14T21:37:14.707 回答
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调用只是将回调添加到要从浏览器的事件处理循环触发的函数队列中。

于 2013-07-14T21:41:12.747 回答