2016-04-14 22 views
2

我有此Javascript代码。Javascript循环通过数组无限无效

var headlineStore = [ 
    function headline1(){ 
     //irrelevant code 
    }, 
    function headline2(){ 
     //irrelevant code 
    }, 
    function headline4(){ 
     //irrelevant code 
    }, 
    function headline4(){ 
     //irrelevant code 
    }, 
    function headline5(){ 
     //irrelevant code 
    } 
] 


for(var i = 0; i < headlineStore.length; i++){ //for loop to loop through array named headlineStore 

    if(i == 4) //if condition to reset the counter once it reaches 5 
    { 
     i = 0; 
    } 

    (function(i){ 
     setTimeout(function(){ 
      headlineStore[i](); 
     }, 5000 * i); 
    }(i)); //Will load each function in the array with timeout increments 
} 

我在这里是一个循环,通过充满函数的数组循环。在每次迭代中,数组中的一个函数将被检索并按时间间隔执行。

我想要的是,在检索到最后一个函数之后,它会从第一个函数开始再次遍历数组,并将无限次地执行此操作。

我试过的是在计数器达到4时重置计数器,但它会离开循环并继续执行,然后出于某种原因页面无响应。

+1

你正在做的不对..尝试改变,你必须使用* * setInterval的逻辑,而不是*的* –

+0

我几乎别想这个代码,而我的头asploding。 –

+1

这种方法将非常迅速地创建数百万个定时器并耗尽可用资源。我怀疑这是一个要求。 – Tibrogargan

回答

2

您需要等到将下一个暂停前的最后一个执行:

var headlineStore = [ 
 
    function headline1(){ 
 
     document.write('1'); 
 
    }, 
 
    function headline2(){ 
 
     document.write('2'); 
 
    }, 
 
    function headline3(){ 
 
     document.write('3'); 
 
    }, 
 
    function headline4(){ 
 
     document.write('4'); 
 
    }, 
 
    function headline5(){ 
 
     document.write('5'); 
 
    } 
 
] 
 

 
function nextHeadline(index) { 
 
    headlineStore[index](); 
 
    window.setTimeout( 
 
    nextHeadline.bind(undefined, (index + 1) % headlineStore.length), 1000); 
 
} 
 

 
nextHeadline(0);

+0

使用绑定的道具以避免创建另一个函数来提供一个参数,但为什么绑定vs应用或调用,因为无论如何你都不关心你的上下文? – Tibrogargan

+0

这个工作谢谢:) – user3703944

+2

@Tibrogargan,'setTimeout'想要一个函数(或字符串?)作为第一个参数,它'bind'给我们。你打算把“通话”放在哪里? – flatline

1

问题是,在第一次超时触发第一个数组函数之前,此函数将永远循环。您需要在超时功能内增加循环。并让它等待。

试试这个:

var headlineStore = [ 
    function headline1(){ 
     //irrelevant code 
    }, 
    function headline2(){ 
     //irrelevant code 
    }, 
    function headline3(){ 
     //irrelevant code 
    }, 
    function headline4(){ 
     //irrelevant code 
    }, 
    function headline5(){ 
     //irrelevant code 
    } 
] 


var i = 0; 

function loopForever(){ 
    setTimeout(function(){ 
     headlineStore[i](); 
     i++; 
     if(i == 5){ 
      i = 0; 
     } 
     loopForever(); 
    }, 5000 * (i + 1)); // I added the +1, else your first function fires immediately. seemed like you didn't want that. 
} 
+1

在第一个setTimeout的回调运行之前,它会循环***无限***,而不是“大约十亿次”。因此回调将永远不会运行。 – Paulpro

+0

downvote?为了什么?我的代码不会无限循环。再读一遍。该函数运行一次并退出。它会在超时结束时再次被调用。 SMH。 –

+0

@我不是在谈论你的代码,我在谈论关于OP代码的答案顶部的陈述。 – Paulpro

0

您可以利用.queue().promise()

var headlineStore = [ 
 
    function headline1(next) { 
 
    //irrelevant code 
 
    console.log("headline1"); 
 
    setTimeout(next, 5000); 
 
    }, 
 
    function headline2(next) { 
 
    //irrelevant code 
 
    console.log("headline2"); 
 
    setTimeout(next, 5000); 
 
    }, 
 
    function headline3(next) { 
 
    //irrelevant code 
 
    console.log("headline3"); 
 
    setTimeout(next, 5000); 
 
    }, 
 
    function headline4(next) { 
 
    //irrelevant code 
 
    console.log("headline4"); 
 
    setTimeout(next, 5000); 
 
    }, 
 
    function headline5(next) { 
 
    //irrelevant code 
 
    console.log("headline5"); 
 
    setTimeout(next, 5000); 
 
    } 
 
]; 
 

 
(function cycle() { 
 
    return $({}).queue("headlines", $.map(headlineStore, function(headline, i) { 
 
     return headline 
 
    })).dequeue("headlines") 
 
    .promise("headlines") 
 
    .then(cycle) // loop infinitely 
 
}());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"> 
 
</script>

1

我认为这是一起的,你需要什么样的线以上(调用1种功能的每一5秒)。用于该用途的setTimeout的支持取决于浏览器

var timeoutHandle = undefined; 

headlineStore = 
[ function1 
, function2 
, function3 
    ... 
]; 

function showHeadline(idx) { 
    headlineStore[idx](idx); 
    timeoutHandle = setTimeout(showHeadline, 5000, (idx+1)%headlineStore.length); 
} 

showHeadline(0); 
+1

前增加我如果你真的想阻止它,'setTimeout'返回可以传递给'clearTimeout'。 – flatline

+0

@flatline感谢手柄,增加:) – Tibrogargan

0

我不知道你试图达到什么目的,但我会尝试解释你的代码不工作的原因。

JS在单线程上运行,并且您在setTimeoutsetInterval中放入的任何函数都在event queue中排队。 这个event queue的函数只有在你的JS代码运行的主要版本是免费的时候才能运行。

为了解释什么,我说,按照这个代码

(function() { 

    // A function queued to be called after 200 ms but it gets called 
    // only when the main thread has finished executing this piece of 
    // code inside the IIFE 
    setTimeout(function() { 
     console.log('Intended to be called after 200 ms delay, however called after the blocking completed'); 
    }, 200); 

    // However the main thead is intentionally blocked here for 5 sec 
    // so the queued call can only happen post this IIFE has finished 
    // execution. 

    console.log('About to start 5 sec blocking'); 
    var now = +new Date; 
    while(+new Date - now < 5e3); // simulating 5 sec blocking 
    console.log('blocking complete.'); 

})(); 

为了更好地理解队列和相关的东西,我会建议看What the heck is Event Loop

现在,正在添加回到你的问题,你无意中创造了一个当您在if(i == 4)区块中设置i = 0时,无限循环。 因此,最终,您将排队函数在事件队列中,但不释放主线程。 因此,事件队列永远不会有机会执行。

function first() { 
    console.log('hello from first function'); 
} 

function second() { 
    console.log('hello from second function'); 
} 

function third() { 
    console.log('hello from third function'); 
} 

function fourth() { 
    console.log('hello from fourth function'); 
} 

function fifth() { 
    console.log('hello from fifth function'); 
} 

var array = [first, second, third, fourth, fifth]; 

for (var i = 0, len = array.length; i < len; i++) { 

    if (i == 4) { i = 0;} // this causes infinite loop 

    console.log('I became an infinite loop'); 

    // functions are added to the queue, but the main thread is stuck in an infinite loop 
    // hence cannot execute these timeouts 
    (function(i) { 
     setTimeout(function() { 
      array[i](); 
     }, 1e2*i); 
    })(i); 
} 

因此,您需要一种方法来调用函数数组。这对我来说似乎是递归的一个用例。 我希望你能轻松实现。