为什么一些JavaScript开发人员使用setTimeout一毫秒?
我在使用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
一毫秒?
这是一个老黑客。 如果需要在另一个事件之后触发事件,则可以使用1ms的setTimeout
来确保在另一个事件之后触发事件。
Short 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,这可能导致在此期间执行不同的function,并且这可能对整个UI过程产生不希望的影响。
为什么首先排队?
如今,浏览器通过观察长时间运行的function来阻止客户端function挂起当前的浏览器会话。 如果某个特定函数运行的时间足够长,浏览器Javascript执行引擎将暂停它并询问用户是否要终止它(将其终止)或等待它完成。
当您确实具有长时间运行function时,这通常是不希望的效果。 例如,假设您有一个函数必须遍历处理过程中每个项目的大量项目。 您绝对不希望用户终止进程,因为循环需要执行。
在这种情况下,解决方案是什么? 在这种情况下,您不必使用循环并执行它的单个函数,而是使用循环(排队)函数,然后将函数调用排入队列以处理每个项目。 这只是这种function的外部骨架。
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引擎重置其函数挂起计时器 。 但请注意,在执行您的function时,您的UI可能会无响应或至多无法预测。 最好对你的函数进行排队,在两者之间留出一些时间空间,这样如果需要,UI就会保持响应。
我认为,因为trigger('update')
内部有一个setTimeout
,只有通过设置另一个setTimeout
你才能实现所需的语句执行顺序。 如果你不通过setTimeout
调用'sorton'
,它将在'update'
之前执行。
另一方面,我猜'update'
使用setTimeout
来防止’update’成为阻塞函数,因为它可能需要很长时间才能执行。