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

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

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

以下代码片段等待大约 2 秒,然后一次打印 61 五十次。

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行。如何打印所有数字?

I thought that I am asking the browser to stop for two seconds after each iteration of the inner loop and then print the numbers.

您只是误解了 setInterval 的性质。当您调用 setInterval 时,您说的是:

Browser, I am going to give you a function, and I want you to run that function every two seconds until I tell you to stop.

做您希望做的事情的一种正确方法是:

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.

告诉浏览器停止

虽然这很难遵循,因此根据您实际尝试完成的目标,可能有更好的方法。例如,如果您尝试遍历几个数组,交叉连接方式,您可以 flatten your arrays out first, removing the need for one of your iterators. Or you could use a library like RxJS to zip the values you want with an interval timer.

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); });