为什么setInterval一次记录所有数据,而不是每次等待指定的时间间隔

Why is setInterval logging all data at once instead of waiting for specified interval each time?

本文关键字:等待 时间 setInterval 一次 记录 数据 为什么      更新时间:2023-09-26

我想用for循环每隔两秒打印一些数字。在所有这些代码片段中都需要外循环,因为我需要它来进行其他操作,所以请不要说不需要两个循环。

下面的代码片段等待大约2秒,然后一次打印50次。

for(var i=0;i<1;i++) { 
    for(var j=1;j<51;j++) {
        window.setInterval(function(){
            console.log(10*i + j);
        }, 2000);
    }  
}

我认为它会打印1——等待2秒——打印2——等待2秒——以此类推。我认为我要求浏览器在每次循环迭代后停止两秒钟,然后打印数字。此外,我认为打印将在外部循环的一次迭代后停止,但它没有,控制台继续打印61。还有一件事,为什么打印61?

编辑:在zerkms的注释之后,我现在有以下代码:
for(var i=0;i<1;i++) { 
    for(var j=1;j<51;j++) {
        window.setTimeout(function(){
            console.log(10*i + j);
        }, 2000*j);
    }  
}

它以2秒的间隔打印50行,但每次都保持打印61行。我怎样才能打印出所有的数字?

我认为我要求浏览器在每次内循环迭代后停止两秒钟,然后打印数字。

你只是误解了setInterval的本质。当你调用setInterval时,你在说:

浏览器,我要给你一个函数,我要你每两秒钟运行一次,直到我让你停止。

做你想做的事情的一个正确方法是:

var i = 0;
var j = 1;
var interval = window.setInterval(function(){
    console.log(i, j);
    j++;
    if(j > 50) {
        j = 0;
        i++;
        if(i > 4) {
            window.clearInterval(interval);
        }
    }
}, 2000);

你会注意到你不需要任何循环,因为setInterval已经会为你重复你的函数。如果没有循环,则需要将递增逻辑(i = 0i++等)移动到普通语句中。然后,一旦你想停止,你必须通过clearInterval告诉浏览器停止。

这很难遵循,所以根据你真正想要完成的事情,很可能有更好的方法。例如,如果您试图以交叉连接的方式遍历一对数组,您可以先将数组平展,从而消除对迭代器的需求。或者你可以使用像RxJS这样的库来用间隔计时器zip你想要的值。

var everyTwoSeconds = Rx.Observable.interval(2000);
var firstSetOfThings = Rx.Observable.from(['one', 'two', 'three']);
var secondSetOfThings = Rx.Observable.range(1, 50);
var allTheThings = firstSetOfThings.flatMap(secondSetOfThings, function(x, y) {
    return "first: " + x + ", second: " + y;
});
everyTwoSeconds.zip(allTheThings, function(i, thing) { console.log(thing); });