每个循环中的 settimeout 有问题
Posted
技术标签:
【中文标题】每个循环中的 settimeout 有问题【英文标题】:having issue with the settimeout in a each loop 【发布时间】: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 = [];
)
【问题讨论】:
【参考方案1】:time*i
- 这可能是你的问题。
以您提供的数据为例,您会得到以下时间:6000
、3000
、12000
。
让我们将这些乘以i
,你会得到0
、3000
、24000
。
编辑: 正如下面的 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()
将不会按时运行,如果其他东西在它触发时正在运行。
【讨论】:
不完全正确。 ***.com/questions/2734025/… @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)); );以上是关于每个循环中的 settimeout 有问题的主要内容,如果未能解决你的问题,请参考以下文章
js经典面试问题:如何让for循环中的setTimeout()函数像预想中一样工作?
循环遍历数组并一次显示单个项目,动态持续时间,如 react js 中的 setTimeout 或 SetInterval