javascript 无延迟呼叫设置

pxiryf3j  于 12个月前  发布在  Java
关注(0)|答案(5)|浏览(122)

在JavaScript库中经常看到这样的代码:

setTimeout(function() {
    ...
}, 0);

字符串
我想知道为什么使用这样的 Package 器代码。

czq61nw1

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?。这是所有接触前端代码的人必须查看的内容。

2w3kk1z5

2w3kk1z52#

你这么做有几个原因

  • 有一个操作你不想立即运行,但想在不久的将来运行。
  • 您希望允许setTimeoutsetInterval中以前注册的其他处理程序运行
ttygqcqt

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';

字符串
这就是我使用它的原因。

vnzz0bqm

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风格的代码,而不会导致递归。

wz8daaqr

wz8daaqr5#

以允许执行任何先前设置的超时。

相关问题