简体   繁体   中英

I am having trouble using setInterval

I've been working on this the last couple of days, it seems so simple but I cant get it to work right. I am trying to display a fact about rabbits every 10 seconds. I've written the array, the loop, and the function, but it keeps only displaying the last item in the array.

var bunnyArr = ["Rabbits don't eat root vegetables, such as carrots", "baby rabbits are called kittens", "A group of rabbits are called a fluffel"];

function bunnyStat() {

    for (i = 0; i < bunnyArr.length; i++) {
        document.getElementById('listItem1').textContent = bunnyArr[i]
    }

}
setInterval(bunnyStat, 10000);

Its not throwing me any errors either, so I am at a loss.

Your function loops through all the array at once, that's why you see just the last one.

Keep a counter outside the function and increment it on each call:

 var bunnyArr = ["Rabbits don't eat root vegetables, such as carrots", "baby rabbits are called kittens", "A group of rabbits are called a fluffel"]; var index = 0; var total = bunnyArr.length; function bunnyStat() { if (index == total) { index = 0; } document.getElementById('listItem1').textContent = bunnyArr[index++]; } setInterval(bunnyStat, 10000); 
 <div id="listItem1"></div> 

This is because bunnyStat() is looping through all three elements of the array very rapidly, ending on the last one. Try something like this instead:

var lastBunnyStat = 0;
var bunnyArr = [
  "Rabbits don't eat root vegetables, such as carrots",
  "baby rabbits are called kittens",
  "A group of rabbits are called a fluffel"
];

function bunnyStat() {
  document.getElementById('listItem1').textContent = bunnyArr[lastBunnyStat++];
  if (lastBunnyStat >= bunnyArr.length) {
    lastBunnyStat = 0;
  }
}

setInterval(bunnyStat, 10000);

I know exactly what is your problem, my students do the same all the time. It's because you understand the concept of timer wrong:

The timer will be called every 10000ms (= 10 seconds). You have to let setInterval take care of the loop. The only thing you have to do in bunnyStat is to implement the "inside of the loop", which means you have to display one stat.

In order to keep track of which have been displayed already, you have to do something to a variable outside the funtion. For example, you could remove the stat from the list.

This is because when you call the function after each interval, the loop runs for bunnyArr.length times and sets the text to bunnyArr[i] ie, for the first iteration, it sets the value to "Rabbits don't eat root vegetables, such as carrots" and next iteration, it sets the value to "baby rabbits are called kittens" and finally in the last iteration, the value is set to the last array item. And this is why you only see the last item.

var bunnyArr = ["Rabbits don't eat root vegetables, such as carrots", "baby rabbits are called kittens", "A group of rabbits are called a fluffel"];

var index = 0;

function bunnyStat() {
    document.getElementById('listItem1').textContent = bunnyArr[index];
    if(index<bunnyArr.length-1){
      index++;
    }else{
      index=0;
    }  
}
setInterval(bunnyStat, 10000);

Others have given the right answers. Here as a bonus, I have randomised the array instead of looping on the same sequence.

  var lastBunnyStat = 0;
  var bunnyArr = [
    "Rabbits don't eat root vegetables, such as carrots",
    "Baby rabbits are called kittens",
    "A group of rabbits are called a fluffel",
    "Rabbits can turn their ears 180 degrees",
    "Their ears can pinpoint the exact location of a sound",
    "Rabbits don’t make good pals."
  ];
  bunnyArr.sort(function() {
        return 0.5 - Math.random();
  });
  // console.log(bunnyArr);

  function bunnyStat() {

    document.getElementById('listItem1').textContent = bunnyArr[lastBunnyStat++];
    if (lastBunnyStat >= bunnyArr.length) {
      lastBunnyStat = 0;
      bunnyArr.sort(function() {
          return 0.5 - Math.random();
      });
      // console.log('endofloop');console.log(bunnyArr);
    }
  }

  setInterval(bunnyStat, 1200);//change to 10000

One "complicated" way to solve this would be using ES6 generators. These generators basically allow you to run a function "split up" into pieces.

When you call a normal function, the function runs to completion, before giving you control back, in the original case, this ment that only the last side-effect was visible.

Generator functions are differend, when you call them, no user provided code is executed, and you get a "control" object back. This control object that you received has differend methods, but in our example we are only interested in the next method.

When the next method is executed, the code of your generator gets executed, till it executes the yield keyword, this saves the execution state, and then pauses the execution of the function again, ready for the next iteration when you call next .

While generators may be to powerful for this problem (other answers are way simpler), they have the advantage that your code becomes easy to read, because you no longer have to declare your variables outside the function, and you usually more frequently read a code than write it.

 var bunnyArr = ["Rabbits don't eat root vegetables, such as carrots", "baby rabbits are called kittens", "A group of rabbits are called a fluffel"]; function* bunnyStat() { while(true) { for (let i = 0; i < bunnyArr.length; i++) { document.getElementById('listItem1').textContent = bunnyArr[i]; yield; } } } const generator = bunnyStat(); generator.next(); setInterval(() => generator.next(), 10000); 
 <div id="listItem1"></div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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