简体   繁体   English

棘手的setTimeout序列

[英]tricky setTimeout sequence

Set of setTimeout calls with intervals 0,1,2,3. setTimeout调用集,间隔为0、1、2、3。

 function f() { setTimeout(function a() {console.log(10);}, 3); setTimeout(function b() {console.log(20);}, 2); setTimeout(function c() {console.log(30);}, 1); setTimeout(function d() {console.log(40);}, 0); } f(); 

Output: (from chrome. Hope would be the same in other browsers) 输出:(来自chrome。希望其他浏览器也一样)

30 三十

40 40

20 20

10 10

Can someone explain clearly why is the ordering not 30, 40, 10, 20? 有人可以清楚地解释为什么订购不是30、40、10、20吗? It is said browsers maintain a minimum 10ms or (spec says) 4ms interval. 据说浏览器至少维持10毫秒或(规定)4毫秒的间隔。 If so, validate the output with time metrics or whichever is convenient to explain this behavior. 如果是这样,请使用时间量度或解释该行为的便利方式来验证输出。 What minute detail am I missing to understand this awesome feature of the language? 为了了解这种语言的强大功能,我错过了什么细节?

Edited: 编辑:

I know these functions are asynchronous. 我知道这些功能是异步的。 And I have read John Resig' blog couple of times. 我已经读过约翰·雷西格(John Resig)的博客几次。 And I know a setTimeout' callback is not guaranteed to execute at the interval specified. 而且我知道setTimeout的回调不能保证在指定的时间间隔执行。

To be more precise, I expect an explanation that can explain the behavior in terms of execution queue, event loop, call stacks and timers. 更准确地说,我希望能有一个可以从执行队列,事件循环,调用堆栈和计时器的角度解释行为的解释。

In order to understand how the timers work internally there's one important concept that needs to be explored: timer delay is not guaranteed. 为了了解计时器在内部的工作方式,有一个重要的概念需要探讨:不能保证计时器的延迟。 Since all JavaScript in a browser executes on a single thread asynchronous events (such as mouse clicks and timers) are only run when there's been an opening in the execution. 由于浏览器中的所有JavaScript都在单线程上执行,因此异步事件(例如鼠标单击和计时器)仅在执行中存在空缺时才运行。

Refer this and this for more details 请参阅了解更多详情

As @Jebin pointed out in a comment to the OP, you're running into a race condition here. 正如@Jebin在对OP的评论中指出的那样,您在这里遇到了竞争状况。

Here's the spec: https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowtimers-settimeout 规格如下: https : //html.spec.whatwg.org/multipage/webappapis.html#dom-windowtimers-settimeout

Step 13 is where we wait, and that waiting can happen while script is currently executing. 步骤13是我们等待的地方,等待可能在脚本当前正在执行时发生。 See http://jsbin.com/faguli/edit?js,console - in this example "10" is logged first because the script takes a long time to get to the next setTimeout . 请参阅http://jsbin.com/faguli/edit?js,console-在此示例中,由于脚本花费很长时间才能到达下一个setTimeout ,因此首先记录“ 10”。

At a guess, in Chrome, the task for 3rd setTimeout is queued before JS manages the 4th call to setTimeout . 猜测,在Chrome中,第3个setTimeout的任务在JS管理对setTimeout的第4个调用之前排队。

So, in this case both Chrome and Firefox are spec-compliant, despite giving different answers. 因此,尽管给出了不同的答案,但在这种情况下,Chrome和Firefox都符合规范。

One way to make this deterministic would be to process setTimeout calls as part of a microtask, and start the timers from there, but setTimeout is an olllllld API, so changes here may break the web. 确定性的一种方法是将setTimeout调用作为微任务的一部分处理,然后从那里启动计时器,但是setTimeout是olllllld API,因此此处的更改可能会中断网络。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM