【问题标题】:Using Random Number Generator for a Loop Timeout使用随机数生成器进行循环超时
【发布时间】:2021-04-30 15:13:00
【问题描述】:

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

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 秒的暂停。但是,当我删除 cmets 以添加行 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

我该如何解决这个问题?

【问题讨论】:

  • 我猜你希望他们一个接一个地开始,而不是像现在这样同时所有超时?抱歉,我可能在你的问题中读多了。
  • @OskarGrosser 有趣的是,每次迭代实际上都使用了生成的超时。因此,当X = 0 超时实际上是 6 秒等。虽然有时,甚至不是这种情况。

标签: javascript loops random timeout


【解决方案1】:

我重写了你的代码。 我认为主要问题是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);

【讨论】:

    【解决方案2】:

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

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

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

    一种方法是使用一个异步函数,该函数返回一个承诺和await,然后滚动到下一个元素为Josh points out

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

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

    【讨论】:

      猜你喜欢
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多