JavaScript循环显示30个随机数仅出现一个,求问题原因
嘿,我来帮你拆解下问题根源,再给你几个可行的解决方案~
为什么只显示一个随机数?
你的runOnLoop函数里的for循环是同步执行的——它会在几毫秒内就跑完30次循环,把30个setTimeout全部塞进浏览器的事件队列里。而这些setTimeout的延迟时间都是2000ms,所以它们会在差不多同一时间触发回调函数。
当30个runRandomNumbers几乎同时执行时,displayContent会快速把innerHTML覆盖30次,你的眼睛根本跟不上这个速度,只能捕捉到最后一次的结果,所以看起来就只显示了一个随机数。
解决方案
我们需要让每个随机数的显示依次延迟触发,也就是第一个数等2秒显示,第二个在第一个显示后再等2秒,以此类推。这里给你两种实用的实现方式:
方式1:递归函数(最可控)
递归可以精准控制每次触发的时机,还能方便地计数停止:
var javascriptElement = "numbers-display"; var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; function displayContent(content) { document.getElementById(javascriptElement).innerHTML = content; }; function runRandomNumbers(array) { displayContent(array[Math.floor(Math.random() * 10)]); }; // 递归实现依次延迟显示 function runSequentially(fn, arg, currentCount, totalTimes) { // 达到次数就停止递归 if (currentCount >= totalTimes) return; fn(arg); // 2秒后执行下一次 setTimeout(function() { runSequentially(fn, arg, currentCount + 1, totalTimes); }, 2000); } // 调用:总共显示30次,每次间隔2秒 runSequentially(runRandomNumbers, numbers, 0, 30);
方式2:用let绑定循环变量(贴近原代码逻辑)
利用let的块级作用域特性,让每个setTimeout捕获到不同的延迟时间:
var javascriptElement = "numbers-display"; var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; function displayContent(content) { document.getElementById(javascriptElement).innerHTML = content; }; function runRandomNumbers(array) { displayContent(array[Math.floor(Math.random() * 10)]); }; function runOnLoop(fn, arg) { for (let i = 0; i < 30; i++) { // 每个循环的延迟是i*2000ms,实现依次触发 setTimeout(function() { fn(arg); }, i * 2000); }; } runOnLoop(runRandomNumbers, numbers);
补充:你之前的
setInterval方案其实也能修复 你提到用setInterval时无法计数停止,其实只需要在回调里维护一个计数器,达到次数就调用clearInterval就行:
var count = 0; var intervalId = setInterval(function() { runRandomNumbers(numbers); count++; // 达到30次就停止定时器 if (count >= 30) { clearInterval(intervalId); } }, 2000);
内容的提问来源于stack exchange,提问作者Michael Alexander
相关产品推荐
相关产品推荐

