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

时间:2021-12-17 03:35:46

This question already has an answer here:

这个问题在这里已有答案:

I have problem when using jQuery plugin tablesorter and I can't call trigger twice.

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

For example this won't work:

例如,这不起作用:

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

But this works:

但这有效:

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

And then I see that problem was in trigger 'update', it call method with body:

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

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

Why did the tablesorter developer use setTimeout with one millisecond?

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

3 个解决方案

#1


13  

It's an old hack. If an event needs to be triggered after another event you can use setTimeout with 1ms to make sure the event is triggered after the other event.

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

#2


15  

Short asnwer: Function execution queueing

This is the short answer to your question. setTimeout with either 0 or 1 millisecond is used for function execution queueing. Read on to find out why and how.

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

Javascript has single threaded execution

Javascript engine is a single threaded process. So whenever developers wanted to defer some function execution to get executed right after the current one that's just being executed, a setTimeout is being used to actually queue the next function... It doesn't have anything to do directly with events although functions may be event handlers. The only event in this equation is the timeout event that setTimeout creates.

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

This is an example of two functions where the first function during its execution queues a second function to be executed right after it.

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

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
}

So to javascript engine thread the execution queue looks like this:

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

first()
second()

Mind that this has nothing to do with function call stack.

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

Why 1ms?

1ms is a very short amount of time, which (almost) assures that your second function will get executed right after your first function returns. You may see sometimes even 0ms which actually executes it right after first function returns.

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

If one would on the other hand use longer time i.e. 100ms this could result in a different function getting executed in the meantime and that could have an undesired effect on the whole UI process.

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

Why function queueing in the first place?

Browsers nowadays prevent client side functionality to hang current browser session by observing long running functions. If a particular function runs long enough, browser Javascript execution engine will pause it and ask the user whether they want to terminate it (kill it) or wait for it to complete.

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

This is usually undesired effect when you actually do have a long running function. For instance imagine you have a function that has to loop through a large number of items processing each one during the process. You definitely don't want the user to terminate the process because the loop needs to execute.

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

What's the solution in this case? In such case instead of having a single function with loop and executing it, you'd rather have the loop (queueing) function that would then queue function calls for processing each item. This is just an outer skeleton of such functionality.

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

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
}

This way you'd prevent your functions to run too long and after each executed function control would get back to Javascript engine resetting its function-hang timer. But be aware that while your functions are being executed your UI will likely be unresponsive or at most unpredictable. It may be better to queue your function with some time space in between so UI stays responsive if that's desired.

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

#3


1  

I think that since trigger('update') internally has a setTimeout, only by setting another setTimeout you can achieve the desired order of statement execution. If you don't call 'sorton' through setTimeout it will be executed before 'update'.

我认为,因为触发器('update')内部有一个setTimeout,只有通过设置另一个setTimeout,你才能实现所需的语句执行顺序。如果你不通过setTimeout调用'sorton',它将在'update'之前执行。

On the other hand I guess 'update' uses setTimeout for preventing 'update' from being a blocking function when it may take a long time to be executed.

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

#1


13  

It's an old hack. If an event needs to be triggered after another event you can use setTimeout with 1ms to make sure the event is triggered after the other event.

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

#2


15  

Short asnwer: Function execution queueing

This is the short answer to your question. setTimeout with either 0 or 1 millisecond is used for function execution queueing. Read on to find out why and how.

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

Javascript has single threaded execution

Javascript engine is a single threaded process. So whenever developers wanted to defer some function execution to get executed right after the current one that's just being executed, a setTimeout is being used to actually queue the next function... It doesn't have anything to do directly with events although functions may be event handlers. The only event in this equation is the timeout event that setTimeout creates.

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

This is an example of two functions where the first function during its execution queues a second function to be executed right after it.

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

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
}

So to javascript engine thread the execution queue looks like this:

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

first()
second()

Mind that this has nothing to do with function call stack.

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

Why 1ms?

1ms is a very short amount of time, which (almost) assures that your second function will get executed right after your first function returns. You may see sometimes even 0ms which actually executes it right after first function returns.

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

If one would on the other hand use longer time i.e. 100ms this could result in a different function getting executed in the meantime and that could have an undesired effect on the whole UI process.

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

Why function queueing in the first place?

Browsers nowadays prevent client side functionality to hang current browser session by observing long running functions. If a particular function runs long enough, browser Javascript execution engine will pause it and ask the user whether they want to terminate it (kill it) or wait for it to complete.

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

This is usually undesired effect when you actually do have a long running function. For instance imagine you have a function that has to loop through a large number of items processing each one during the process. You definitely don't want the user to terminate the process because the loop needs to execute.

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

What's the solution in this case? In such case instead of having a single function with loop and executing it, you'd rather have the loop (queueing) function that would then queue function calls for processing each item. This is just an outer skeleton of such functionality.

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

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
}

This way you'd prevent your functions to run too long and after each executed function control would get back to Javascript engine resetting its function-hang timer. But be aware that while your functions are being executed your UI will likely be unresponsive or at most unpredictable. It may be better to queue your function with some time space in between so UI stays responsive if that's desired.

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

#3


1  

I think that since trigger('update') internally has a setTimeout, only by setting another setTimeout you can achieve the desired order of statement execution. If you don't call 'sorton' through setTimeout it will be executed before 'update'.

我认为,因为触发器('update')内部有一个setTimeout,只有通过设置另一个setTimeout,你才能实现所需的语句执行顺序。如果你不通过setTimeout调用'sorton',它将在'update'之前执行。

On the other hand I guess 'update' uses setTimeout for preventing 'update' from being a blocking function when it may take a long time to be executed.

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