我是一名JavaScript新手,我试图通过setInterval
和setTimeout
实现并发行动。
我想要实现的目标,实际发生的事情以及我期望发生的事情最好用以下代码解释。
var myVar = setInterval(function() {
myTimer()
}, 1000);
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
for (var i = 0; i < 100; i++) {
setTimeout(function() {
console.log("log " + i);
}, 3000);
}
&#13;
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
&#13;
我对领先setInterval
的期望是,函数myTimer
每秒执行一次,与之后发生的情况无关。当然,除非网站已关闭或clearTimeout
已调用myVar
。
我无法验证此操作是否真正独立且持续发生。
以下for循环,用于模拟更多代码,以查看myTimer
函数是否将独立执行。
我希望循环以i=0
开头,然后等待三秒钟,将log 0
记录到控制台,然后继续i=1
,依此类推。
相反,似乎超时已开始,同时i
已到达for循环的结尾,因此100
。
如何让for循环等待setTimeout
?
setInterval
是否真的每秒执行一次,与以下代码无关?例如。如果以下代码的操作需要一些处理/时间,那么在处理过程中,时钟会不会更新吗?
答案 0 :(得分:2)
您可以使用因子i
更改超时时间,并使用i
上的闭包来获得正确的值。
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
var i,
myVar = setInterval(myTimer, 1000);
for (i = 0; i < 100; i++) {
setTimeout(function (i) {
return function() {
console.log("log " + i);
};
}(i), 3000 * i);
}
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
超时后调用超时的版本。
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
function next() {
i++;
console.log("log " + i);
if (i < 300) {
setTimeout(next, 3000);
}
}
var i = 0,
myVar = setInterval(myTimer, 1000);
setTimeout(next, 3000);
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
答案 1 :(得分:1)
关于你的setInterval
问题,是的。它会每秒运行一次(不是一丝不苟)。我们假设您只是设置了setInterval
,然后运行需要半秒钟才能运行的操作。间隔将计为半秒,然后再运行半秒。硬编码不会延迟时钟, BUT ,如果您在间隔应该触发的时刻运行代码,它将等待该代码结束,因为JavaScript是单线程的。这意味着如果在设置间隔后立即运行持续时间超过1秒的代码,则会在其后运行间隔回调,因此不会在1秒内触发。顺便说一下,后续的间隔调用将在此间隔之后调用,但是在设置间隔之后调用。检查这个小提琴(F12):https://jsfiddle.net/0gggmemu/4/
您会看到代码结束时调用第一个间隔,但是在设置间隔时会调用后续间隔(检查毫秒,它们如何适合第一个日志而不是起始日志)。请注意,间隔不会堆叠。如果它应该调用10个间隔,它将只调用一个并等待下一个。如果时间精度对您很重要,那么您应该在启动时保存参考并检查每个时间间隔的差异。
关于并发性,与调用setInterval
时相同,当您调用setTimeout
时,代码将继续执行,同时创建数百个超时。如果你想要代码挂起,请检查我的小提琴。顺便说一句,如果您担心setTimeout
锁定setInterval
,请不要担心,因为代码不会被阻止。如果你的代码卡在某处,你只需要担心,但在回调驱动的应用程序中很难实现这一点。