你能用setInterval来异步调用函数吗?

时间:2012-02-17 06:06:16

标签: javascript asynchronous setinterval

以下代码取自Project Silk(Microsoft示例应用程序) 下面的发布方法循环通过一个事件callBacks数组并执行每一个。而不是使用for循环而是使用setInterval。

文档说明这允许在上一次回调结束之前调用每个订阅者回调。它是否正确?我认为浏览器不会允许在间隔内执行该函数,直到它的所有先前执行完成为止。

这和for循环有什么不同吗?

that.publish = function (eventName, data) 
{
    var context, intervalId, idx = 0;
    if (queue[eventName]) 
    {
        intervalId = setInterval(function () 
        {
            if (queue[eventName][idx]) 
            {
                context = queue[eventName][idx].context || this;
                queue[eventName][idx].callback.call(context, data);
                idx += 1;
            } 
            else { clearInterval(intervalId); }
        }, 0);
    }

2 个答案:

答案 0 :(得分:4)

setInterval(..., 0)可用于控制浏览器UI,以防止代码需要很长时间才能运行。

在这种情况下,that.publish几乎会在执行任何回调之前立即退出。然后每个回调将“在后台”运行 - 它们将被放置在事件循环中,并且每个回调都将在下一次回调执行之前向浏览器发出信号。

这在事件处理中似乎是一个好主意,因为你不希望事件处理冻结浏览器,即使它们有很多或者有些需要很长时间才能完成。

关于文档 - 如上所述,它是不正确的。 Javascript是单线程的。但是如果你要连续几次调用publish(),那么在执行任何回调之前,这些调用都会完成,因为setTimeout。也许这就是文档的意思?

答案 1 :(得分:4)

在这里使用setInterval会使执行排序为“异步”,因为它会在下次主执行线程可用时安排回调的执行。

这意味着回调执行不应该阻止浏览器,因为在回调之前会发生任何其他同步处理(因为回调只安排在主执行线程有一个备用毫秒时运行) - 这就是构造“比常规for循环更好” - 回调不会阻止浏览器并导致可怕的“此页面有一个花费太长时间的脚本”错误。

这种调度模式的副作用是超时只是一个“建议” - 这就是他们在这里使用0的原因。

请参阅:http://ejohn.org/blog/how-javascript-timers-work/