为什么一些JavaScript开发人员使用setTimeout一毫秒?

时间:2012-08-21 09:18:50

标签: javascript jquery settimeout tablesorter

使用jQuery插件tablesorter时遇到问题,我无法调用触发器两次。

例如,这不起作用:

this._$table.trigger('update');
this._$table.trigger('sorton', [[[1,1]]]);

但这有效:

this._$table.trigger('update');
setTimeout($.proxy(function() {
    this._$table.trigger('sorton', [[[1,1]]]);
}, this), 1);

然后我发现问题出现在触发器'update'中,它用body调用方法:

function () {
    var me = this;
    setTimeout(function () {
        // rebuild parsers.
        me.config.parsers = buildParserCache(
        me, $headers);
        // rebuild the cache map
        cache = buildCache(me);
    }, 1);
}

为什么tablesorter开发人员使用setTimeout一毫秒?

3 个答案:

答案 0 :(得分:15)

短asnwer:功能执行排队

这是您的问题的简短答案。具有0或1毫秒的setTimeout用于功能执行排队。继续阅读以找出原因和方法。

Javascript具有单线程执行

Javascript引擎是一个单线程进程。因此,每当开发人员想要将某个函数执行推迟到刚刚执行的当前函数执行之后,就会使用setTimeout来实际对下一个函数进行排队 ...它没有'尽管函数可能是事件处理程序,但它与事件直接相关。此等式中唯一的事件是setTimeout创建的超时事件。

这是两个函数的示例,其中第一个函数在执行期间将第二个函数排在其后立即执行。

function first()
{
    // does whatever it needs to

    // something else needs to be executed right afterwards
    setTimeout(second, 1);

    // do some final processing and exit
    return;
}

function second()
{
    // whatever needs to be done
}

因此,对于javascript引擎线程,执行队列如下所示:

first()
second()

请注意,与函数调用堆栈无关。

为什么1ms?

1ms是一个非常短的时间,它(几乎)确保你的第二个函数将在你的第一个函数返回后立即执行。您可能会看到有时甚至 0ms 实际上在第一个函数返回后立即执行

如果另一方面使用更长的时间,即100ms,这可能导致在此期间执行不同的功能,这可能会对整个UI过程产生不良影响。

为什么首先排队?

现在,浏览器通过观察长时间运行的功能来阻止客户端功能挂起当前的浏览器会话。如果某个特定函数运行的时间足够长,浏览器Javascript执行引擎会暂停它并询问用户是否要终止它(终止它)或等待它完成。

当您确实具有长时间运行功能时,这通常是不希望的效果。例如,假设您有一个函数必须遍历处理过程中每个项目的大量项目。你肯定不希望用户终止进程,因为循环需要执行。

在这种情况下解决方案是什么?在这种情况下,您不必使用循环并执行它的单个函数,而是使用循环(排队)函数,然后将函数调用排入队列以处理每个项目。这只是这种功能的外部骨架。

function queueItems(items) {
    for(var i = 0; i < items.length, i++)
    {
        setTimeout((function(item) {
            return function() {
                processItem(item);
            };
        })(items[i]), 0);
    }
}

function processItem(item) {
    // process individual item
}

这样你就可以防止你的函数运行太长时间,并且每次执行的函数控制都会返回到Javascript引擎重置其函数挂起计时器。但请注意,在执行您的功能时,您的UI可能会无响应或至多无法预测。最好对您的函数进行排队,其间有一些时间空间,因此如果需要,UI会保持响应。

答案 1 :(得分:14)

这是一个老黑客。如果需要在另一个事件之后触发事件,则可以使用setTimeout和1ms来确保在另一个事件之后触发事件。

答案 2 :(得分:1)

我认为,由于trigger('update')内部有一个setTimeout,只有通过设置另一个setTimeout,您才能实现所需的语句执行顺序。如果您未通过'sorton'致电setTimeout,则会在'update'之前执行。

另一方面,我猜'update'使用setTimeout来阻止'update'成为阻塞函数,因为它可能需要很长时间才能执行。