简体   繁体   English

Javascript事件队列是否优先?

[英]Does Javascript event queue have priority?

These days, I have read some documents about setTimeout, setInterval. 这些天,我已经阅读了一些关于setTimeout,setInterval的文档。 I have learned that the Javascript is a single thread which will only execute one piece of code per time. 我了解到Javascript是一个单独的线程,每次只执行一段代码。 At the same time, if there is a event happens, it will be pushed into the event queue and block until appropriate time. 同时,如果发生事件,它将被推入事件队列并阻塞直到适当的时间。 I want to to know, when many events are blocked waiting to execute at the same time. 我想知道,当许多事件被阻止等待同时执行时。 Is these events have different priorities, so the high priority event will execute before the low ones. 这些事件是否具有不同的优先级,因此高优先级事件将在低优先级事件之前执行。 Or just a FIFO queue. 或者只是一个FIFO队列。

setTimeout(fn1, 10);
$(document).click(fn2); //will be called at 6ms;
$.ajax({ajaxSuccess(fn3); //async request,it uses 7ms;})

 for () {
    //will run 18ms;
};

In the above code, the setTimeout fn1 will happen at 10 ms,click event handler fn2 will at 6ms, ajax callback fn3 will at 7ms, but all the three functions will be blocked until the for loop finish. 在上面的代码中,setTimeout fn1将在10毫秒发生,点击事件处理程序fn2将在6毫秒,ajax回调fn3将在7毫秒,但所有三个函数将被阻止,直到for循环结束。 At 18ms, the for loop finished, so what order does these functions will be invoked.(fn1,fn2,fn3) or (fn2,fn3,fn1) 在18ms时,for循环结束,所以调用这些函数的顺序是什么。(fn1,fn2,fn3)或(fn2,fn3,fn1)

Work scheduled for the main JavaScript thread is processed FIFO. 为主JavaScript线程安排的工作是FIFO处理。 This includes callbacks from various async tasks, such as setTimeout and ajax completions, and event handlers. 这包括来自各种异步任务的回调,例如setTimeout和ajax完成,以及事件处理程序。 The only exception is that in the main popular environments (browsers and Node), the resolution callback of a native Promise jumps the queue (more accurately, goes in a different higher-priority queue), see my answer here for details on that. 唯一的例外是在主流的环境(浏览器和节点)中,本机Promise的解析回调会跳过队列(更准确地说,是在不同的更高优先级队列中),有关详细信息,请参阅我的答案

But leaving aside native promise resolution callbacks: 但抛开原生承诺解决回调:

but all the three functions will be blocked until the for loop finish. 但是这三个函数都将被阻塞,直到for循环结束。 At 18ms, the for loop finished, so what order does these functions will be invoked. 在18ms时, for循环结束,所以这些函数的调用顺序是什么。 (fn1,fn2,fn3) or (fn2,fn3,fn1) (fn1,fn2,fn3)或(fn2,fn3,fn1)

The time you give setTimeout is approximate, because when that time comes due the JavaScript UI thread may be busy doing something else (as you know); 你给setTimeout的时间是近似的,因为当那个时候到来时,JavaScript UI线程可能正在忙着做其他事情(如你所知); there's also a minimum time required by the (newish) spec, but the degree to which it's enforced varies by implementation. (新的)规范还需要最短的时间,但实施的程度因实施而异。 Similarly, you can't guarantee that the click event will be queued at 6ms, or that the ajax completion will occur at exactly 7ms. 同样,您不能保证 click事件将在6ms排队,或者ajax完成将在7ms完成。

If that code started, and the browser did the 10ms precisely, and the click event was queued exactly 6ms in, and the ajax request completed at exactly 7ms, then the order would be: fn2 (the click handler), fn3 (the ajax completion), fn1 (the setTimeout ), because that's the order in which they'd be queued. 如果该代码启动,并且浏览器精确地完成了10ms,并且click事件排队正好排队6ms, 并且 ajax请求正好在7ms完成,那么顺序将是: fn2click处理程序), fn3 (ajax完成) ), fn1setTimeout ),因为这是他们排队的顺序。

But note that these are extremely tight timings. 但请注意,这些是非常紧张的时间。 In practice, I expect the order the callbacks were queued would be effectively random, because the timing of the click would vary, the timing of the ajax would vary, etc. 实际上,我希望回调排队的顺序实际上是随机的,因为click的时间会有所不同, ajax的时间会有所不同等等。

I think this is a better example: 我认为这是一个更好的例子:

var start = +new Date();

// Queue a timed callback after 20ms
setTimeout(function() {
    display("20ms callback");
}, 20);

// Queue a timed callback after 30ms
setTimeout(function() {
    display("30ms callback");
}, 30);

// Queue a timed callback after 10ms
setTimeout(function() {
    display("10ms callback");
}, 10);

// Busy-wait 40ms
display("Start of busy-wait");
var stop = +new Date() + 40;
while (+new Date() < stop) {
    // Busy-wait
}
display("End of busy-wait");

function display(msg) {
    var p = document.createElement('p');
    var elapsed = String(+new Date() - start);
    p.innerHTML = "+" + "00000".substr(elapsed.length - 5) + elapsed + ": " + msg;
    document.body.appendChild(p);
}

The order of output will be the two loop messages followed by the 10ms callback, 20ms callback, and 30ms callback, because that's the order in which the callbacks are queued for servicing by the main JavaScript thread. 输出的顺序是两个循环消息,后跟10ms回调,20ms回调和30ms回调,因为这是回调排队等待主JavaScript线程服务的顺序。 For instance: 例如:

+00001: Start of busy-wait
+00041: End of busy-wait
+00043: 10ms callback
+00044: 20ms callback
+00044: 30ms callback

...where the + numbers indicate milliseconds since the script started. ...其中+数字表示自脚本启动以来的毫秒数。

Does javascript event queue have priority? javascript事件队列有优先权吗?

Sort of. 有点。 The event loop is actually composed of one or more event queues. 事件循环实际上由一个或多个事件队列组成。 In each queue, events are handled in a FIFO order. 在每个队列中,事件以FIFO顺序处理。

It's up to the browser to decide how many queues to have and what form of prioritisation to give them. 由浏览器决定要拥有多少队列以及为其提供哪种优先级形式。 There's no Javascript interface to individual event queues or to send events to a particular queue. 单个事件队列没有Javascript接口或将事件发送到特定队列。

https://www.w3.org/TR/2014/REC-html5-20141028/webappapis.html#event-loops https://www.w3.org/TR/2014/REC-html5-20141028/webappapis.html#event-loops

Each task is defined as coming from a specific task source. 每个任务都定义为来自特定任务源。 All the tasks from one particular task source and destined to a particular event loop (eg the callbacks generated by timers of a Document, the events fired for mouse movements over that Document, the tasks queued for the parser of that Document) must always be added to the same task queue, but tasks from different task sources may be placed in different task queues . 必须始终添加来自一个特定任务源并发往特定事件循环的所有任务(例如,由Document的计时器生成的回调,针对该Document的鼠标移动而触发的事件,排队等待该Document的解析器的任务)到同一个任务队列,但来自不同任务源的任务可以放在不同的任务队列中

For example, a user agent could have one task queue for mouse and key events (the user interaction task source), and another for everything else. 例如,用户代理可以为鼠标和键事件(用户交互任务源)创建一个任务队列,为其他所有事件设置另一个任务队列。 The user agent could then give keyboard and mouse events preference over other tasks three quarters of the time, keeping the interface responsive but not starving other task queues, and never processing events from any one task source out of order. 然后,用户代理可以在四分之三的时间内为其他任务提供键盘和鼠标事件首选项,保持界面响应但不会使其他任务队列处于饥饿状态,并且从不处理来自任何一个任务源的事件。

FIFO. FIFO。 There really isn't anything more to say. 真的没有什么可说的了。 You don't get to schedule it. 你无法安排它。

This can be a bit of a pain when you're looking at multiple timeout operations that could conceivably happen at the same time. 当您查看可能同时发生的多个超时操作时,这可能会有点痛苦。 That said, if you're using Asynchronous behaviors you shouldn't be depending on how they get scheduled. 也就是说,如果您使用的是异步行为,则不应该依赖于它们的安排方式。

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

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