使用随机数生成器实现循环超时

Using Random Number Generator for a Loop Timeout

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

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

我该如何解决这个问题?

我重写了你的代码。 我认为主要问题是 setTimeout 是非阻塞的。 我用promiseawait一起解决了

function sleep(time) {
    return new Promise(resolve => setTimeout(resolve, time));
}

function randomGen(max, min) {
    return Math.floor(Math.random() * (max - min + 1) + min);
}

async function randomWaitAndScroll(elements, timeMin, timeMax) {
  for (element of elements) {
    let random = randomGen(timeMin, timeMax)
    await sleep(random);
    element.scrollIntoView({behavior: 'smooth'});
  }
}

const containerElements = document.querySelectorAll('.chunk-container');
randomWaitAndScroll(containerElements, 3000, 9000);

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

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

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

一种方法是在滚动到下一个元素

之前使用一个异步函数,该函数 returns 一个承诺和 await

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

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