在JavaScript库中经常看到这样的代码:
setTimeout(function() { ... }, 0);
字符串我想知道为什么使用这样的 Package 器代码。
czq61nw11#
非常简单:浏览器是单线程的,这个单线程(UI线程)在渲染引擎和js引擎之间共享。如果你想做的事情需要很多时间(我们在这里说的是循环,但仍然),它可能会停止(暂停)渲染(流动和绘制)。在浏览器中也存在“存储桶”,所有的事件首先被放置在那里等待UI线程完成它正在做的任何事情。一旦线程完成,它就会在存储桶中查找并选择第一个任务。使用setTimeout,您可以在延迟之后在存储桶中创建一个新任务,并让线程在有更多工作可用时立即处理它。一个故事:0毫秒延迟后,创建一个新的函数任务并将其放入桶中。此时,UI线程正忙碌其他事情,而桶中已经有另一个任务了。6毫秒后,线程可用,并将任务放在你的前面,很好,你是下一个。但是什么?这是一件大事!它就像foreeeeever(30毫秒)!!最后,现在线程完成了这个任务,并获得了你的任务。大多数浏览器的最小延迟都大于0,因此将0作为延迟意味着:把这个任务尽快放到篮子里。但是告诉UA把它尽快放到水桶里并不能保证它在那一刻就能执行。水桶就像邮局,这可能是因为有一长串的其他任务。邮局也是单线程的,只有一个人帮助所有的任务...抱歉客户的任务。你的任务必须和其他人一样排队。如果浏览器没有实现自己的时钟,它将使用操作系统的时钟周期。旧版浏览器的最小延迟在10- 15 ms之间。HTML5规定,如果延迟小于4 ms,UA应将其增加到4 ms。据说,这在2010年及以后发布的浏览器中是一致的。有关更多详细信息,请参见John Resig的How JavaScript Timers Work。
setTimeout
**编辑:**另请参阅Philip Roberts在JSConf EU 2014中的What the heck is the event loop anyway?。这是所有接触前端代码的人必须查看的内容。
2w3kk1z52#
你这么做有几个原因
setInterval
ttygqcqt3#
当你想执行剩下的代码而不等待前一个代码完成时,你需要将它添加到传递给setError函数的匿名方法中。否则你的代码将等待前一个代码完成。
示例:
function callMe() { for(var i = 0; i < 100000; i++) { document.title = i; } } var x = 10; setTimeout(callMe, 0); var el = document.getElementById('test-id'); el.innerHTML = 'Im done before callMe method';
字符串这就是我使用它的原因。
vnzz0bqm4#
除了前面的答案,我想添加另一个我能想到的有用的场景:从try-catch块中“escape”。来自try-catch块中的setTimeout-delay将在块外执行,任何异常都将在全局范围内传播。也许最好的例子场景:在当今的JavaScript中,由于异步回调中更常见的是所谓的Deferreds/Promises,因此您(通常)实际上是在try-catch中运行的。Deferreds/Promises将回调 Package 在try-catch中,以便能够检测并传播异常作为异常链中的错误。这对于需要在链中的函数来说都很好,但迟早你会“完成”(即获取所有的异常),并希望在你不希望异常被“隐藏”的地方运行普通的非Java代码。AFAIK Dojo,Kris科瓦尔的Q,MochiKit和Google Closure lib使用try-catch Package (但不是jQuery)。(On在一些奇怪的情况下,我也使用了这种技术来重新启动singleton风格的代码,而不会导致递归。
wz8daaqr5#
以允许执行任何先前设置的超时。
5条答案
按热度按时间czq61nw11#
非常简单:
浏览器是单线程的,这个单线程(UI线程)在渲染引擎和js引擎之间共享。
如果你想做的事情需要很多时间(我们在这里说的是循环,但仍然),它可能会停止(暂停)渲染(流动和绘制)。
在浏览器中也存在“存储桶”,所有的事件首先被放置在那里等待UI线程完成它正在做的任何事情。一旦线程完成,它就会在存储桶中查找并选择第一个任务。
使用
setTimeout
,您可以在延迟之后在存储桶中创建一个新任务,并让线程在有更多工作可用时立即处理它。一个故事:
0毫秒延迟后,创建一个新的函数任务并将其放入桶中。此时,UI线程正忙碌其他事情,而桶中已经有另一个任务了。6毫秒后,线程可用,并将任务放在你的前面,很好,你是下一个。但是什么?这是一件大事!它就像foreeeeever(30毫秒)!!
最后,现在线程完成了这个任务,并获得了你的任务。
大多数浏览器的最小延迟都大于0,因此将0作为延迟意味着:把这个任务尽快放到篮子里。但是告诉UA把它尽快放到水桶里并不能保证它在那一刻就能执行。水桶就像邮局,这可能是因为有一长串的其他任务。邮局也是单线程的,只有一个人帮助所有的任务...抱歉客户的任务。你的任务必须和其他人一样排队。
如果浏览器没有实现自己的时钟,它将使用操作系统的时钟周期。旧版浏览器的最小延迟在10- 15 ms之间。HTML5规定,如果延迟小于4 ms,UA应将其增加到4 ms。据说,这在2010年及以后发布的浏览器中是一致的。
有关更多详细信息,请参见John Resig的How JavaScript Timers Work。
**编辑:**另请参阅Philip Roberts在JSConf EU 2014中的What the heck is the event loop anyway?。这是所有接触前端代码的人必须查看的内容。
2w3kk1z52#
你这么做有几个原因
setTimeout
或setInterval
中以前注册的其他处理程序运行ttygqcqt3#
当你想执行剩下的代码而不等待前一个代码完成时,你需要将它添加到传递给setError函数的匿名方法中。否则你的代码将等待前一个代码完成。
示例:
字符串
这就是我使用它的原因。
vnzz0bqm4#
除了前面的答案,我想添加另一个我能想到的有用的场景:从try-catch块中“escape”。来自try-catch块中的setTimeout-delay将在块外执行,任何异常都将在全局范围内传播。
也许最好的例子场景:在当今的JavaScript中,由于异步回调中更常见的是所谓的Deferreds/Promises,因此您(通常)实际上是在try-catch中运行的。Deferreds/Promises将回调 Package 在try-catch中,以便能够检测并传播异常作为异常链中的错误。这对于需要在链中的函数来说都很好,但迟早你会“完成”(即获取所有的异常),并希望在你不希望异常被“隐藏”的地方运行普通的非Java代码。AFAIK Dojo,Kris科瓦尔的Q,MochiKit和Google Closure lib使用try-catch Package (但不是jQuery)。
(On在一些奇怪的情况下,我也使用了这种技术来重新启动singleton风格的代码,而不会导致递归。
wz8daaqr5#
以允许执行任何先前设置的超时。