I have this Javascript code.
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
}
What I have here is a for loop that loops through an array filled with functions. On every iteration a function from the array is retrieved and executed with time intervals.
What I want is that after the last function is retrieved it loops through the array again starting with the first function and will do this infinitely.
What I tried is resetting the counter when it reaches 4 but it goes out of the loop and continue executing, then for some reason the page bee unresponsive.
I have this Javascript code.
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
}
What I have here is a for loop that loops through an array filled with functions. On every iteration a function from the array is retrieved and executed with time intervals.
What I want is that after the last function is retrieved it loops through the array again starting with the first function and will do this infinitely.
What I tried is resetting the counter when it reaches 4 but it goes out of the loop and continue executing, then for some reason the page bee unresponsive.
Share Improve this question edited Apr 14, 2016 at 18:25 user3703944 asked Apr 14, 2016 at 18:18 user3703944user3703944 713 silver badges9 bronze badges 8- 1 You are doing that wrong.. try to change the logic that you have to use setInterval, instead of for – Hugo S. Mendes Commented Apr 14, 2016 at 18:22
- I can hardly even think about this code without my head asploding. – Dave Newton Commented Apr 14, 2016 at 18:23
- 1 This approach is going to create millions of timers very quickly and exhaust available resources. I doubt that's a requirement. – Tibrogargan Commented Apr 14, 2016 at 18:25
- This is an infinite loop. It will crash the page or browser depending on OS and browser types. – Travis J Commented Apr 14, 2016 at 18:27
- 1 What you have here is an XY problem. You created an infinite loop to do some work, but have not shown what work needs an infinite loop to be acplished. – Travis J Commented Apr 14, 2016 at 18:28
5 Answers
Reset to default 4You need to wait until the last one executes before setting the next timeout:
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);
I think this is more along the lines of what you need (call 1 function every 5 seconds). Support for this use of setTimeout depends on the browser
var timeoutHandle = undefined;
headlineStore =
[ function1
, function2
, function3
...
];
function showHeadline(idx) {
headlineStore[idx](idx);
timeoutHandle = setTimeout(showHeadline, 5000, (idx+1)%headlineStore.length);
}
showHeadline(0);
You can utilize .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./ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
I don't know what you are trying to achieve, but I will try explaining why your code is not working.
JS runs on single thread and any function you put in setTimeout
or setInterval
is queued in the event queue
.
Functions from this event queue
are run only when the main thead on which your JS code was running is free.
To explain what I said, follow this code
(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 pleted');
}, 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 plete.');
})();
To better understand the queue and related stuff, I would remend watching What the heck is Event Loop
Now, ming back to your question, you inadvertantly created an infinite loop when you set i = 0
in the if(i == 4)
block.
So, ultimately, you are queuing the functions in the event queue, but not freeing the main thread.
Hence the event queue never get a chance to execute.
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);
}
Therefore, you need a way to call an array of functions on and on. This seems to me a use case for recursion. I hope that you could achieve easily.
The problem is that this function will loop forever before the first timeout ever fires the first array function. You need to increment the loop within the timeout function. and make it wait.
Try this:
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.
}