我在使用 setInterval 时遇到问题



最近几天我一直在研究这个问题,它看起来很简单,但我无法让它正常工作。我试图每 10 秒显示一次关于兔子的事实。我已经编写了数组、循环和函数,但它只显示数组中的最后一项。

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

它也不会给我带来任何错误,所以我不知所措。

你的函数一次遍历所有数组,这就是为什么你只看到最后一个数组。

在函数外部保留一个计数器,并在每次调用时递增它:

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>

我确切地知道你的问题是什么,我的学生一直在做同样的事情。这是因为你对计时器的概念理解错误:

计时器将每 10000 毫秒(= 10 秒)调用一次。你必须让setInterval照顾循环。bunnyStat中,您唯一需要做的就是实现"循环内部",这意味着您必须显示一个统计信息。

为了跟踪已经显示的内容,您必须对函数之外的变量执行一些操作。例如,您可以从列表中删除统计信息。

这是因为bunnyStat()非常快速地循环遍历数组的所有三个元素,在最后一个元素结束。请尝试以下操作:

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

其他人给出了正确的答案。作为奖励,我随机化了数组,而不是在同一序列上循环。

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

这是因为当你在每个间隔后调用函数时,循环运行 bunnyArr.length 时间并将文本设置为 bunnyArr[i],即,对于第一次迭代,它将值设置为"兔子不吃根茎类蔬菜,如胡萝卜",下一次迭代,它将值设置为"小兔子被称为小猫",最后在最后一次迭代中, 该值设置为最后一个数组项。这就是为什么你只看到最后一项。

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

解决这个问题的一种"复杂"方法是使用 ES6 生成器。这些生成器基本上允许您将函数"拆分"为多个部分运行。

当你调用一个普通函数时,函数运行到完成,然后把控制权交还给你,在原始情况下,只有最后一个副作用是可见的。

生成器函数是不同的,当你调用它们时,不会执行用户提供的代码,并且你会得到一个"控制"对象。您收到的此控件对象具有不同的方法,但在我们的示例中,我们只对next方法感兴趣。

当执行next方法时,生成器的代码被执行,直到它执行yield关键字,这将保存执行状态,然后再次暂停函数的执行,为调用next时的下一次迭代做好准备。

虽然生成器可能很强大(其他答案更简单),但它们的优点是你的代码变得易于阅读,因为你不再需要在函数之外声明你的变量,而且你通常更频繁地阅读代码而不是编写它。

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>

最新更新