【问题标题】:having issue with the settimeout in a each loop每个循环中的 settimeout 有问题
【发布时间】:2012-09-06 01:46:18
【问题描述】:

我正在尝试循环一些以毫秒为单位的值。我需要每隔 xxxx 秒运行一些代码,具体取决于他从循环中获得的值,但我无法让它工作,它工作得很好,但它没有按时运行。

代码包含一个重置按钮(代码来自插件,但我不得不修改它)

//插件选项

  step:[
      {
          time: 6000,
          // more stuff here 
          // but we dont need 
          // it in this example
      },
      {
          time: 3000,
          // more stuff here 
          // but we dont need 
          // it in this example
      },
      {
          time: 12000,
          // more stuff here 
          // but we dont need 
          // it in this example
      }
  ]

// 循环

  var timeouts = [];
  $.each(options.step, function(i, value){

      var time =  value.time;                                                       
      timeouts.push(setTimeout(function(){

          alert('some action');

      },time*i));

  });

//重置按钮

  $('.stop').click(function(){
      $.each(timeouts, function (_, id) {
          clearTimeout(id);
      });
      timeouts = [];
  })

【问题讨论】:

    标签: javascript jquery settimeout each


    【解决方案1】:

    time*i - 这可能是你的问题。

    以您提供的数据为例,您会得到以下时间:6000300012000

    让我们将这些乘以i,你会得到0300024000

    编辑: 正如下面的 cmets 中所建议的,您希望第一个值始终为零,而结果值则保持原样。

    将超时延迟设置为i == 0 ? 0 : time 会起作用。

    这基本上意味着expression ? true : false;

    这是一个例子:http://jsfiddle.net/2ka9g/1/

    【讨论】:

    • 只是不要乘以i。只需使用time
    • 然后使用i == 0 ? 0 : time;
    • 不起作用,看起来它在继续之前循环了值 2
    【解决方案2】:

    我的主要猜测是您没有设置所需的计时器时间。您使用i * value.time 作为您的计时器时间,这看起来很奇怪。你是否意识到i 是你数组的索引,所以第一次它会是零,然后是 1,然后是 2,等等......

    这将导致计时器时间为:0*6000, 1*3000, 2*12000,转换为 0, 3000, 24000

    这似乎不是你想要的。

    此外,浏览器中的 Javascript 是单线程的(除了 webWorkers 和一些我们在这里不讨论的事件副作用)。因此,setTimeout() 不保证准确。如果在计时器事件触发时正在运行其他东西,则该计时器事件将进入事件队列,并将稍后在当前 Javascript 执行线程完成时运行。因此,setTimeout() 将不会按时运行,如果其他东西在它触发时正在运行。

    【讨论】:

    • @BlakeRegalia - 那篇文章与上下文或 OP 的问题无关(例如 setTimeout() 的时间)。
    • 只是说,最好不要在不承认极端情况的情况下就 JavaScript 做出粗体、笼统的陈述。感谢您编辑您的答案
    • @BlakeRegalia - 根据我所知道的单线程与多线程的任何定义,该文章中描述的事件触发仍然是单线程的。没有两个 javascript 执行线程同时进行。某些事件处理程序可能会因为您调用 .focus() 而运行这一事实就像一个同步函数调用。它不是多线程的。如果您的代码设计不佳并且需要注意,但仍然是单线程的,则可能会导致问题。当然,整个问题与setTimeout() 触发的时间无关。
    【解决方案3】:

    您设置的时间间隔将为 0 秒 (6000 * 0)、3 秒 (3000 * 1) 和 24 秒 (24000 * 2)。这是因为您要乘以索引 (i)。这是您要达到的时间间隔吗?

    【讨论】:

    • 好吧,如果我只使用值它会起作用(这是我第一次使用),但现在它具有不同的值。
    • 那么是索引器的使用导致了这个错误吗?如果没有,请指定您要通过具体间隔实现的目标。
    • 好吧,我正在尝试每 xxx 秒运行一段代码(取决于值),如果我在上面的示例中使用固定值 10000,它将运行一段代码,然后等待继续前 10 秒,运行一段代码并等待 10 秒等。是的,我认为索引不是正确的值,也不是不同的值。
    • 你不需要乘以索引器。删除该表达式 (time*i)。由于闭包函数作用域,您也不需要 time 变量: var timeouts = []; $.each(options.step, function(i, value){ timeouts.push(setTimeout(function(){ alert('some action'); },value.time)); });
    猜你喜欢
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    相关资源
    最近更新 更多