javascript - 理解 setTimeout
问题描述
我一直试图让一系列句子在前一个句子之后 2 秒出现,使用 setTimeout 显示每个句子,并使用 setInterval 重复这个过程一定次数(由用户定义)。
以下示例代码显示了我的理解和困惑:
var myComments = document.getElementById("comments");
var subtractor = 5;
var timer, myRun;
window.onload = onStart();
function onStart() {
alert("First Comment");
myRun = setInterval(function() {
alert("Sub = " + subtractor);
setTimer("<p>This is a first sentence. Subtractor = " + subtractor + "</p>");
setTimer("<p>This is a second sentence. Subtractor = " + subtractor + "</p>");
setTimer("<p>This is a third sentence. Subtractor = " + subtractor + "</p>");
subtractor = subtractor - 1;
if (subtractor < 1) {
alert("Subtractor to clear");
clearInterval(myRun);
}
}, 2000);
alert("Last Comment");
}
function setTimer(setText) {
clearTimeout(timer);
timer = setTimeout(function() {myComments.innerHTML = myComments.innerHTML + setText;}, 2000);
}
<div id="comments"></div>
警报只是作为测试点存在,表明我缺乏理解:
- 为什么在第一个警报之后立即显示最后一个警报,然后在 setInterval 内显示警报?- 因为 setTimeout 是异步的!
- 为什么除了生成的最后一句话外,没有任何句子显示?- 由于它们是异步的,因此下一个计时器取消前一个计时器,只显示最后一个计时器。
- 我哪里错了?如何让句子一个接一个地出现,每个句子之间有两秒钟的延迟?我是否将每个计时器嵌套在前一个?
抱歉,最后一个问题更多的是我自己的想法;去测试!
解决方案
为什么在第一个警报之后立即显示最后一个警报,然后在 setInterval 内显示警报?
最后一个警报不在 setTimeout 或 setInterval 内,因此会立即触发。其他的都在 2000 毫秒的 setTimeout 内,所以两秒钟后触发(一次全部)。
为什么除了生成的最后一句话外,没有任何句子显示?
您正在以相同的 2000 毫秒延迟同时触发三个 setTimeouts,因此两秒后它们几乎同时触发三个。它们内部的 clearTimeouts 相互冲突(因为您重复使用相同的timer
变量来跟踪它们),这阻止了它们中的两个被触发。
我哪里错了?
您对 setTimer 的每个调用都应该使用不同的时间延迟,这样它们就不会一次全部触发。同时,setInterval 应该有足够长的间隔,这样它就不会在它设置的三个 setTimeouts 完成之前循环。无需在 setTimout 调用上调用 clearTimeout;默认情况下,它们会运行一次然后停止,这就是您想要的。您唯一需要的地方就是停止 setInterval。
您可能还想立即触发第一次迭代,因此它会立即开始,而不是等待第一个间隔完成:
var myComments = document.getElementById("comments");
var subtractor = 5;
var timer, myRun;
window.onload = onStart();
function setTimers() {
//alert("Sub = " + subtractor);
setTimer("<p>This is a first sentence. Subtractor = " + subtractor + "</p>", 0); // no delay
setTimer("<p>This is a second sentence. Subtractor = " + subtractor + "</p>", 2000); // 2s delay
setTimer("<p>This is a third sentence. Subtractor = " + subtractor + "</p>", 4000); // 4s delay
subtractor = subtractor - 1;
if (subtractor < 1) {
//alert("Subtractor to clear");
clearInterval(myRun);
}
}
function onStart() {
//alert("First Comment");
myRun = setInterval(setTimers, 6000); // 6 seconds for the full interval
setTimers(); // so you don't have to wait 6 seconds for the first run
}
function setTimer(setText, delay) {
timer = setTimeout(function() {
myComments.innerHTML = myComments.innerHTML + setText;
}, delay);
}
<div id="comments"></div>
推荐阅读
- artifactory - 如何删除上传到 Artifactory 的柯南包版本(在免费层)
- c++ - 如何手动将我的 C++ 文件发送到 GitHub,而不是在从 GitHub 下载后推送然后成功重新编译?标准做法?
- postgresql - PostGIS ST_ConcaveHull 函数调用上的 lwpoly_from_lwlines 错误
- android - Android Studio (Kotlin) - 切换应用后 VideoView 变黑
- python - 注释日期时间字段的特定属性 - 无法将关键字“toordinal”解析为字段。不允许加入“created_at”
- javascript - d3.hierarchy 正在使用 d3.linkHorizontal() 绘制不存在的节点
- kubernetes - kubernates rook+ceph OSD 全删数据
- javascript - TabView 中不滚动的平面列表(React Native Elements)
- python - 熊猫,日期时间和逻辑:总结一列中特定行的总和
- salesforce - 删除未生效的 Salesforce Scratch Orgs:org:list