首页 > 解决方案 > 使用随机数生成器进行循环超时

问题描述

此脚本应以随机生成的延迟滚动浏览网站上的每个容器。对于循环中的每次迭代,我想2000用随机生成的数字替换 ms的“暂停”。minmax

var min = 3,
    max = 9;
var y = document.querySelectorAll('.chunk-container').length;

for (let x=0; x<y; x++) {
   task(x);
}

function task(x) {
//    var z = randomGen() * 1000;
    setTimeout(function() {
        console.log('X = ' + x + ' Y = ' + y);
            document.getElementsByClassName('chunk chunk-container')[x].scrollIntoView({behavior: 'smooth'});
            console.log('Scrolled to next Container');
    }, /* z */ 2000 * x);
}
})

随机数发生器:

function randomGen() {
    var rand = Math.floor(Math.random() * (max - min + 1) + min);
    console.log('Random Number generated: ' + rand + ' seconds');
    return rand;
}

像这样它工作正常。每次迭代后,会有 2 秒的暂停。但是,当我删除注释以添加行var z = randomGen() * 1000;以随机化每次迭代之间的时间时,x值(它应该滚动到哪个容器)开始时很好,但结果也是随机的。

控制台输出:

Random Number generated: 6 seconds
Random Number generated: 5 seconds
Random Number generated: 4 seconds
Random Number generated: 8 seconds
Random Number generated: 4 seconds
Random Number generated: 8 seconds
X = 0 Y = 7
Scrolled to next Container
X = 1 Y = 7
Scrolled to next Container
X = 2 Y = 7
Scrolled to next Container
X = 4 Y = 7
Scrolled to next Container
X = 3 Y = 7
Scrolled to next Container
X = 5 Y = 7
Scrolled to next Container
X = 6 Y = 7
Scrolled to next Container

我怎样才能解决这个问题?

标签: javascriptloopsrandomtimeout

解决方案


问题是2000 * x因为每次滚动之间的延迟是恒定的,所以你的超时触发在:

  • x = 0-> 0 毫秒
  • x = 1-> 2000 毫秒
  • x = 2-> 4000 毫秒

因此,您在开始时立即启动所有超时,它们最终每 2 秒触发一次,但每个超时的值是不同的。每个都隐含地取决于之前的所有超时都每 2 秒触发一次这一事实。

一种方法是使用异步函数,该函数返回一个承诺,await并在滚动到下一个元素之前为它返回,正如Josh 指出的那样

另一种方法是跟踪先前的超时值并将它们相加,以计算下一个超时值。像这样:

var min = 3,
    max = 9;
var y = document.querySelectorAll('.chunk-container').length;

for (let x=0, accumulatedDelay = 0; x<y; x++) {
    accumulatedDelay += task(x, accumulatedDelay);
}

function task(x, accumulatedDelay) {
    const z = randomGen() * 1000;
    setTimeout(function() {
        console.log('X = ' + x + ' Y = ' + y);
            document.getElementsByClassName('chunk chunk-container')[x].scrollIntoView({behavior: 'smooth'});
            console.log('Scrolled to next Container');
    }, z + accumulatedDelay);

    return accumulatedDelay;
}

推荐阅读