setInterval和setTimeout的并发操作

时间:2017-03-13 11:57:54

标签: javascript concurrency settimeout setinterval

我是一名JavaScript新手,我试图通过setIntervalsetTimeout实现并发行动。

我想要实现的目标,实际发生的事情以及我期望发生的事情最好用以下代码解释。



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;
&#13;
&#13;

我对领先setInterval的期望是,函数myTimer每秒执行一次,与之后发生的情况无关。当然,除非网站已关闭或clearTimeout已调用myVar

我无法验证此操作是否真正独立且持续发生。

以下for循环,用于模拟更多代码,以查看myTimer函数是否将独立执行。

我希望循环以i=0开头,然后等待三秒钟,将log 0记录到控制台,然后继续i=1,依此类推。

相反,似乎超时已开始,同时i已到达for循环的结尾,因此100

如何让for循环等待setTimeout

的迭代

setInterval是否真的每秒执行一次,与以下代码无关?例如。如果以下代码的操作需要一些处理/时间,那么在处理过程中,时钟会不会更新吗?

2 个答案:

答案 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,请不要担心,因为代码不会被阻止。如果你的代码卡在某处,你只需要担心,但在回调驱动的应用程序中很难实现这一点。