0

I'm having trouble Grok'ing a simple JavaScript for loop.

Here is an example:

var arr = ["Banana", "Orange", "Apple", "Mango"];
for (i = 1; i <= 5; ++i) {
  setDelay(i);
}

function setDelay(i) {
  setTimeout(function(){
    for(const value of arr) {
    document.write(value);
    document.write("<br />");
    }
  }, i * 1000);
}

What I'm trying to do is pause after it prints the first value, but instead it runs the entire For loop then pauses. I think I'm trying to do something with for loops that just won't work, but I would like to know why.

Any help would be appreciated.

Plunkr here: https://plnkr.co/edit/tnmFrIRTDJI8T294Qh4z?p=preview

The example Javascript, setTimeout loops? didn't help me figure it out. I still got the concept wrong as George Pantazes points out.

Rostasan
  • 57
  • 9
  • Possible duplicate of [Javascript, setTimeout loops?](https://stackoverflow.com/questions/22154129/javascript-settimeout-loops) – Tyler Roper Nov 13 '18 at 19:05
  • 2
    By running your code, you can see that you are printing the entire array within the `setTimeout`. Instead of looping through the entire `arr` in the `setTimeout` `for` loop, if you access your array like `arr[i]` and only print one item instead of all of them, your code would work as you intend. – George Pantazes Nov 13 '18 at 19:06

3 Answers3

2

Inside setTimeout - instead of printing entire array just print current element.

var arr = ["Banana", "Orange", "Apple", "Mango"];
for (let i = 1; i < 5; ++i) {
  setDelay(i);
}

function setDelay(i) {
  setTimeout(function(){
    console.log(arr[i-1])
  }, i * 1000);
}
Nitish Narang
  • 4,124
  • 2
  • 15
  • 22
  • Why are you using 1-i? Is it better to start with i = 1? I do understand that the array index starts at 0. Oh wait, so the array is four long, so you changed the i to equal 1 match the offset? Would it be better if I did i < arr.length? -Thanks – Rostasan Nov 13 '18 at 20:04
  • Yes, you are correct because you have 4 array elements and array index starts from 0 – Nitish Narang Nov 13 '18 at 20:07
  • Its better to do i< arr.length. Also, its always preferable to start i with 0 rather than 1 – Nitish Narang Nov 14 '18 at 06:45
1

There were multiple issues within your code:

  1. Be sure to mind that Javascript arrays are 0-based. You were starting at 1.
  2. Similarly, be sure to mind the ending bound of the index (in your for loop). It was going too far even for a 1-base (it was going to 5 out of 4 available items)
  3. Within the setTimeout, you were printing the entire array by using for(const value of arr). You were probably trying to pass in i as an index to index only one element.

With those comments in mind, here is the working code with those parts changed:

var arr = ["Banana", "Orange", "Apple", "Mango"];
for (i = 0; i < arr.length; ++i) {
  setDelay(i);
}

function setDelay(i) {
  setTimeout(function(){
    document.write(arr[i]);
    document.write("<br />");
  }, i * 1000);
}
George Pantazes
  • 1,039
  • 3
  • 12
  • 26
  • Refer to @Nitish-Narang's answer for better Javascript code style, although I think my advice about the indices is worth taking as well. – George Pantazes Nov 13 '18 at 19:15
  • wow thanks. I tried to do that by setting i = to the array (out of desperation), but this makes a lot more sense. I have access to the array and i. So that would let me use arr[i]. – Rostasan Nov 13 '18 at 20:01
0

An alternative approach to creating a delay by using setTimeout in a loop is the setInterval function. setInterval will execute the function argument each time a specified duration of of milliseconds passes:

var arr = ["Banana", "Orange", "Apple", "Mango"];
var i = 0;
var intervalId = setInterval(logNext, 1000);

function logNext() {
  if (i < arr.length) {
    console.log(arr[i++]);
  } else {
    console.log('End of array reached!');
    clearInterval(intervalId);
  }
}
Tom O.
  • 5,730
  • 2
  • 21
  • 35