javascript setTimeout 和 array 每个

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17246275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 07:37:16  来源:igfitidea点击:

setTimeout and array each

javascriptunderscore.jssettimeouteach

提问by Kevin

I'm confused with using setTimeout and the each iterator. How can I rewrite the following so that the console outputs each name after a delay of 5 seconds? Currently the code below prints all the names at once after 5 seconds. I would like to:

我对使用 setTimeout 和 each 迭代器感到困惑。如何重写以下内容,以便控制台在 5 秒延迟后输出每个名称?目前,下面的代码会在 5 秒后一次打印所有名称。我想:

1) wait 5 seconds, then print kevin
2) wait 5 seconds, then print mike
3) wait 5 seconds, then print sally

1) 等 5 秒,然后打印 kevin
2) 等 5 秒,然后打印 mike
3) 等 5 秒,然后打印 sally

var ary = ['kevin', 'mike', 'sally'];

_(ary).each(function(person){

  setTimeout(function(){
    console.log(person);
  }, 5000);    

});

回答by LonelyWebCrawler

You could create a variable called offsetthat makes the timer wait 5 seconds more for each person in the array, like so:

您可以创建一个名为的变量offset,使计时器为数组中的每个人多等待 5 秒,如下所示:

var ary = ['kevin', 'mike', 'sally'];

var offset = 0;
_(ary).each(function(person){

  setTimeout(function(){
    console.log(person);
  }, 5000 + offset);    
 offset += 5000;
});

回答by KyleMit

You have three basic options:

您有三个基本选项:

  1. For Loop + setTimeout
    ... initialize everyone immediately, but stagger the start times based on the index position so they don't all go at the same time.
  2. setTimeout+ conditional recursion
    ... check back in every nseconds - and I'll tell you if you need to do another
  3. setInterval+ conditional clearInterval
    ... keep running every nseconds - until I tell you to stop
  1. For Loop +setTimeout
    ... 立即初始化每个人,但根据索引位置错开开始时间,这样它们就不会同时进行。
  2. setTimeout+ 条件递归
    ......每n秒检查一次- 我会告诉你是否需要再做一次
  3. setInterval+ 有条件的clearInterval
    ......每n秒继续运行- 直到我告诉你停止

Here's each one of those fleshed out with a working example:

下面是用一个工作示例充实的每一个:

1. For Loop + setTimeout

1. For 循环 + setTimeout

A couple notes on this one. This is kind of like starting a relay race and handing out instructions ahead of time to each runner to start at precisely 5:00 and 5:02 and 5:04, regardless of whether the person behind them finished a long time ago or hasn't yet arrived.

关于这个的一些说明。这有点像开始接力赛,并提前向每个跑步者发出指令,让他们在 5:00、5:02 和 5:04 开始,无论他们后面的人是很久以前完成还是没有完成”还没到。

Also, you can't use a regular for i=0 loop, because the for operator does not define new function scope. Thus object values set within each for loop will apply across iterations. By the time setTimeout is called, it will only use the most recent value. So we need a closure to store the value within each loop. I've used Array.prototype.forEach(), but if you want to use the forEach implementations in jQuery or Underscore, that'll work too.

此外,您不能使用常规for i=0 loop,因为 for 运算符没有定义新的函数范围。因此,在每个 for 循环中设置的对象值将跨迭代应用。当 setTimeout 被调用时,它只会使用最近的值。所以我们需要一个闭包来存储每个循环中的值。我已经使用过Array.prototype.forEach(),但是如果您想在 jQuery 或 Underscore 中使用 forEach 实现,那也可以。

function ArrayPlusDelay(array, delegate, delay) {
 
  // initialize all calls right away
  array.forEach(function (el, i) {
    setTimeout(function() {
        // each loop, call passed in function
        delegate( array[i]);

      // stagger the timeout for each loop by the index
      }, i * delay);
  })
 
}

// call like this
ArrayPlusDelay(['a','b','c'], function(obj) {console.log(obj)},1000)

2. setTimeout+ conditional recursion

2. setTimeout+ 条件递归

For the bottom two options, we're making our own loops, so we'll have to keep track of the index ourselves, initializing at zero and incrementing throughout.

对于底部的两个选项,我们正在制作自己的循环,因此我们必须自己跟踪索引,初始化为零并始终递增。

For this one, we'll a) call setTimeoutwhich will run once, b) evaluate the array at the index position, c) check if there are more elements in the array and if so, start over at (a).

对于这个,我们将 a) 调用setTimeout将运行一次,b) 在索引位置评估数组,c) 检查数组中是否有更多元素,如果有,则从 (a) 开始。

   
function ArrayPlusDelay(array, delegate, delay) {
  var i = 0
  
  function loop() {
     // each loop, call passed in function
      delegate(array[i]);
      
      // increment, and if we're still here, call again
      if (i++ < array.length - 1)
          setTimeout(loop, delay); //recursive
  }

  // seed first call
  setTimeout(loop, delay);
}

// call like this
ArrayPlusDelay(['d','e','f'], function(obj) {console.log(obj)},1000)

3. setInterval+ conditional clearInterval

3. setInterval+ 有条件的clearInterval

NOTE: The function setIntervalwill run forever once called. It's return value when initially set will provide a reference to the interval, so it is often combined with the function clearIntervalto optionally shut it off down the road

注意setInterval一旦调用该函数将永远运行。初始设置时的返回值将提供对区间的引用,因此它通常与函数结合使用clearInterval以选择性地将其关闭

function ArrayPlusDelay(array, delegate, delay) {
  var i = 0
  
   // seed first call and store interval (to clear later)
  var interval = setInterval(function() {
     // each loop, call passed in function
      delegate(array[i]);
      
        // increment, and if we're past array, clear interval
      if (i++ >= array.length - 1)
          clearInterval(interval);
  }, delay)
  
}

ArrayPlusDelay(['x','y','z'], function(obj) {console.log(obj)},1000)



3* Secret Fourth Option (Best One)

3 * 秘密第四选项(最佳选项)

Options 1 & 2 are risky because, once you set off that train, there's no way to call it off down the road (save closing the browser). If you have a large array or a heavy load in your delegate, it might be nice to provide some recourse if you need it. By saving the reference from setInterval, we'll have constant access to the iterating function. We just need to return the interval object above and save it when calling our array plus delay function.

选项 1 和 2 是有风险的,因为一旦您启动了那列火车,就无法在路上停下来(除了关闭浏览器)。如果您的委托中有一个大型数组或负载很重,那么在需要时提供一些追索权可能会很好。通过保存来自 的引用setInterval,我们将可以持续访问迭代函数。我们只需要在调用我们的数组加延迟函数时,返回上面的interval对象并保存即可。

function ArrayPlusDelay(array, delegate, delay) {
  var i = 0
  
   // seed first call and store interval (to clear later)
  var interval = setInterval(function() {
     // each loop, call passed in function
      delegate(array[i]);
      
        // increment, and if we're past array, clear interval
      if (i++ >= array.length - 1)
          clearInterval(interval);
  }, delay)
  
  return interval
}

var inter = ArrayPlusDelay(['x','y','z'], function(obj) {console.log(obj)},1000)

Then if we ever want to clear it later on, just throw this in the console:

然后,如果我们以后想清除它,只需在控制台中抛出它:

clearInterval(inter);

All 3 Demos in jsFiddle

jsFiddle 中的所有 3 个演示

Similar Stack Overflow Questions:

类似的堆栈溢出问题:

回答by jAndy

You could do

你可以做

var ary = ['kevin', 'mike', 'sally'];

_(ary).each(function(person, index){

  setTimeout(function(){
    console.log(person);
  }, index * 5000);    
});

Without increasing the timeoutvalue, you would initialize all setTimeoutswith the exact same value (thats why you see what you see).

在不增加timeout值的情况下,您将setTimeouts使用完全相同的值初始化所有值(这就是为什么您会看到所见)。

回答by Casey Chu

eachis usually better for things that happen immediately.

each通常对立即发生的事情更好。

Instead, if you don't mind changing the array, you can use it as a queue:

相反,如果您不介意更改数组,则可以将其用作队列:

var ary = ['kevin', 'mike', 'sally'];

setTimeout(function loop() {
    console.log(ary.shift());

    if (ary.length)
        setTimeout(loop, 5000);
}, 5000);

It keeps on calling loop5 seconds in the future until there's nothing left in the queue.

它会在loop未来 5 秒内继续调用,直到队列中没有任何东西为止。

回答by php_nub_qq

You could just use setInterval()with a simple increase-by-one counter.

您可以将setInterval()与一个简单的加一计数器一起使用。

var ary = ['kevin', 'mike', 'sally'];

var i=0;
setInterval(function(){
    console.log(ary[i]);
    i++;
}, 5000);

But note that this will start throwing errors after i becomes greater than two. You need to have some kind of validation there and make sure you clear the interval.

但请注意,这将在 i 大于 2 后开始抛出错误。您需要在那里进行某种验证并确保清除间隔。