简体   繁体   English

建立循环内延时函数调用的列表

[英]Build list of time delayed function calls within loop

I'm trying to make a list of function calls separated by a timed interval. 我正在尝试列出一个函数调用列表,并按一定的时间间隔分隔。 The code below currently takes the last item for each function call. 下面的代码当前占用每个函数调用的最后一项。

The current code prints: itemThree, itemThree, itemThree - each separated by ten seconds 当前代码打印:itemThree,itemThree,itemThree-每个间隔十秒

The desired code prints: itemOne, itemTwo, itemThree - each separated by ten seconds 所需的代码打印出来: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);
}

I'm trying to make a list of timer delayed function calls. 我正在尝试列出计时器延迟的函数调用。 How would I need to change the above code, or is there a better solution? 我将如何更改上面的代码,或者有更好的解决方案? Thanks for yours helps. 感谢您的帮助。

JavaScript passes values by reference , and by the time timeout fires, index will reach its greatest value and therefore "itemThree" will always be shown. JavaScript通过引用传递值,并且在超时触发时, index将达到其最大值,因此将始终显示“ itemThree”。 To fix that, you need to create another scope for the looping variable to live in so it doesn't get changed by outer scope. 要解决此问题,您需要为循环变量创建另一个作用域,以使其不被外部作用域更改。

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

An approach I use in cases like this is to use an immediately invoked function expression in a pseudo-recursive loop to extract the elements from the list one at a time: 我在这种情况下使用的一种方法是在伪递归循环中使用立即调用的函数表达式 ,一次从列表中提取元素:

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

Without the for loop you avoid the issue of the item variable having its last assigned value during each callback. 如果没有for循环,则可以避免在每个回调过程中item变量具有最后分配的值的问题。

With the pseudo-recursive use of setTimeout you also avoid queuing more than one timer at a time. 使用setTimeout的伪递归使用,还可以避免一次排队多个计时器。 I call this usage pseudo-recursive because whilst it may appear that loop is calling itself, in reality the setTimeout call merely adds callbacks to a queue of functions to be triggered from the browser's event processing loop. 我将这种用法称为伪递归,因为尽管看起来loop在调用自身,但实际上setTimeout调用只是将回调添加到要从浏览器事件处理循环触发的函数队列中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM