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

Dmy*_*sun 12 javascript jquery tablesorter settimeout

我在使用jQuery插件tablesorter时遇到问题而且我无法调用触发器两次.

例如,这不起作用:

this._$table.trigger('update');
this._$table.trigger('sorton', [[[1,1]]]);
Run Code Online (Sandbox Code Playgroud)

但这有效:

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

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

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

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

elc*_*nrs 15

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


Rob*_*nik 15

Short asnwer:函数执行排队

这是您的问题的简短答案.setTimeout0或1毫秒用于函数执行排队.请继续阅读以了解原因和方法.

Javascript具有单线程执行

Javascript引擎是一个单线程进程.因此,每当开发人员想要将某个函数执行推迟到刚刚执行的当前执行之后执行时,setTimeout就会使用a来实际排队下一个函数 ...它没有任何事情可以直接处理事件,尽管函数可能是事件处理程序.此等式中唯一的事件是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
}
Run Code Online (Sandbox Code Playgroud)

所以对于javascript引擎线程,执行队列看起来像这样:

first()
second()
Run Code Online (Sandbox Code Playgroud)

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

为什么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
}
Run Code Online (Sandbox Code Playgroud)

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