对于页面上的一个元素,我希望文本每十秒更改一次,并更改类。更改文本很容易,更改类也很容易,但我在使用 for
时遇到了麻烦。循环,我觉得我错过了一些东西。
我想要for loop
在数组中选择一个随机派别,然后将其应用于该元素。对于我的测试,我一直在使用 console.log
而不是 DOM 操作。
首先,我设置了我的数组:
var factions = ["Enforcers", "Reapers", "Ular Boys", "Roaches"];
然后,我想要一个变量,它是引用该数组随机选择的数字:
var x = factions[Math.floor(Math.random()*factions.length)];
由此,我希望能够运行 Math.floor
和Math.random
在其他地方起作用。
function reDefine() {
x = factions[Math.floor(Math.random()*factions.length)];
console.log(x);
}
最后,我想要for loop
运行 200 次(我选择了 200 次,因为它远远超出了用户在网站上停留的时间),所以我告诉它数到 200 ( i = 0; i < 200
)。之后,我希望每次迭代时都等待 10 秒,所以我有一个 Timeout
延迟为 10000
的函数(毫秒)。然后,代码为reDefine
然后,在测试的情况下,console.log
x
的新定义变量。
function reChange() {
for (var i = 0; i < 200; i++) {
setTimeout(function() {
reDefine();
console.log("Chosen faction is now: " + x);
}, 10000);
}
}
<小时/>
而不是数到1
(第一次迭代),等待10000
,然后重新定义x
,它重新定义了x
两百次,然后将它们全部记录下来。
我在这里特别做错了什么,也许是 Timeout
功能?
最佳答案
Is there something I'm specifically doing wrong here, perhaps with the Timeout function?
是的!您正在安排一堆延迟回调,但实际上并没有等到一个回调完成才安排下一个回调。
您可以通过简单的方法来解决这个问题:
function reChange(currentIndex) {
setTimeout(function() {
reDefine();
console.log("Chosen faction is now: " + factions[currentIndex]);
// If we haven't gotten to the end of the list, queue up another one
var nextIndex = ++currentIndex;
if (nextIndex < factions.length) {
// Enqueue the next faction
reChange(nextIndex);
}
}, 10000);
}
请务必注意,没有超时的函数
有 closure每次调用 reChange
时都会超过 currentIndex
的值。也就是说,下一次调用不会替换任何先前超时中的 currentIndex
,因为基元(包括数字)是按值传递的。 Closure in JS can be a tricky thing.
核心问题是你现在的执行看起来像:
- 对于每个项目
- 等等
- 记录
而不是:
- 对于当前项目
- 等等
- 日志
- 重复
因为 JS 是单线程的(对于大多数意图和目的),setTimeout
添加稍后执行的回调。它没有block直到超时结束,就像传统的 sleep 一样。
关于javascript - For 循环迭代同时发生而不是延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37707393/