循环中的 setTimeout。如何获得正确的订单

Posted

技术标签:

【中文标题】循环中的 setTimeout。如何获得正确的订单【英文标题】:setTimeout in a loop. How to get the correct order 【发布时间】:2020-11-17 00:57:23 【问题描述】:

我试图在循环中调用一个函数以实现不同的超时或延迟。

for (var i = 0; i < 10; i++)         
  callDelayedFunction(i);


function callDelayedFunction(i) 
  setTimeout(function () 
    console.log(i);        
  , getRandomInt(1500, 4500) * i);

我期待

1,2,3,4,5,6,7,8,9

但我明白了

1,2,3,4,7,8,5,6,9

我该如何解决这个问题?

【问题讨论】:

你需要使用链式承诺 您的超时是随机的,因此它们以随机顺序触发也就不足为奇了。我不确定我明白你在问什么。 @RobinZigmond 我半信半疑他要求 ti 随机等待 1 时间,然后随机等待 2 时间,然后随机等待 3时间量 哦,好的,这是一个合理的假设 - 谢谢@TKoL(在这种情况下我当然同意你的回答)。 【参考方案1】:

这是一种方法,使用async/await

function callDelayedFunction(i) 
  return new Promise(resolve => 
    setTimeout(function() 
      console.log(i);
      resolve();
    , getRandomInt(1500, 4500) * i);
  )



function getRandomInt(min, max) 
  return Math.floor(Math.random() * (max - min)) + min;


async function run() 
  for (var i = 0; i < 10; i++) 
    await callDelayedFunction(i);
  


run();

【讨论】:

【参考方案2】:

不应该期望数字按顺序打印出来,如果你设置随机超时并且不采取任何步骤来保证第n+1次迭代之后 /em> 第 n 次迭代。

在不改变范式的情况下,您可以通过引入这样的辅助变量来解决任务 - 每个下一个 setTimeout 都使用比前一个更大的延迟参数调用:

var timeoutLimit = 0;

function getRandomInt(low, high) 
  return Math.floor(Math.random() * (high - low) + low);


for (var i = 0; i < 10; i++) 
  callDelayedFunction(i);


function callDelayedFunction(i) 
  var delay = getRandomInt(150, 450) + 1;
  timeoutLimit += delay;
  setTimeout(function() 
    console.log(i);
  , timeoutLimit);

【讨论】:

【参考方案3】:

你可以试试这个。该代码在 3 秒窗口内选择了一个随机时间。这会根据索引值设置窗口。

for (var i = 0; i < 10; i++)         
    callDelayedFunction(i);


function callDelayedFunction(i) 
    let windowLength = 3000;
    let startTime = 1500;
    setTimeout(function () 
        console.log(i);        
    , startTime + getRandomInt(windowLength*i, windowLength*(i+1)));



function getRandomInt(a, b) 
  return Math.floor((Math.random()*(b-a)) + a);

【讨论】:

以上是关于循环中的 setTimeout。如何获得正确的订单的主要内容,如果未能解决你的问题,请参考以下文章

js经典面试问题:如何让for循环中的setTimeout()函数像预想中一样工作?

如何确保所有使用redux的promise中的promise顺序正确?

如何使用php、html及消息队列实现订单超时自动关闭订单

如何使用CoffeeScript重新同步setTimeout()? Rails 5

用纯javascript制作动画或效果的正确方法是什么?

如何使用try和catch来保持循环以获得正确的输入?