[英]Does Javascript event queue have priority?
这些天,我已经阅读了一些关于setTimeout,setInterval的文档。 我了解到Javascript是一个单独的线程,每次只执行一段代码。 同时,如果发生事件,它将被推入事件队列并阻塞直到适当的时间。 我想知道,当许多事件被阻止等待同时执行时。 这些事件是否具有不同的优先级,因此高优先级事件将在低优先级事件之前执行。 或者只是一个FIFO队列。
setTimeout(fn1, 10);
$(document).click(fn2); //will be called at 6ms;
$.ajax({ajaxSuccess(fn3); //async request,it uses 7ms;})
for () {
//will run 18ms;
};
在上面的代码中,setTimeout fn1将在10毫秒发生,点击事件处理程序fn2将在6毫秒,ajax回调fn3将在7毫秒,但所有三个函数将被阻止,直到for循环结束。 在18ms时,for循环结束,所以调用这些函数的顺序是什么。(fn1,fn2,fn3)或(fn2,fn3,fn1)
为主JavaScript线程安排的工作是FIFO处理。 这包括来自各种异步任务的回调,例如setTimeout
和ajax完成,以及事件处理程序。 唯一的例外是在主流的环境(浏览器和节点)中,本机Promise
的解析回调会跳过队列(更准确地说,是在不同的更高优先级队列中),有关详细信息,请参阅我的答案 。
但抛开原生承诺解决回调:
但是这三个函数都将被阻塞,直到for循环结束。 在18ms时,
for
循环结束,所以这些函数的调用顺序是什么。 (fn1,fn2,fn3)或(fn2,fn3,fn1)
你给setTimeout
的时间是近似的,因为当那个时候到来时,JavaScript UI线程可能正在忙着做其他事情(如你所知); (新的)规范还需要最短的时间,但实施的程度因实施而异。 同样,您不能保证 click事件将在6ms排队,或者ajax完成将在7ms完成。
如果该代码启动,并且浏览器精确地完成了10ms,并且click
事件排队正好排队6ms, 并且 ajax请求正好在7ms完成,那么顺序将是: fn2
( click
处理程序), fn3
(ajax完成) ), fn1
( setTimeout
),因为这是他们排队的顺序。
但请注意,这些是非常紧张的时间。 实际上,我希望回调排队的顺序实际上是随机的,因为click
的时间会有所不同, ajax
的时间会有所不同等等。
我认为这是一个更好的例子:
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);
}
输出的顺序是两个循环消息,后跟10ms回调,20ms回调和30ms回调,因为这是回调排队等待主JavaScript线程服务的顺序。 例如:
+00001: Start of busy-wait +00041: End of busy-wait +00043: 10ms callback +00044: 20ms callback +00044: 30ms callback
...其中+
数字表示自脚本启动以来的毫秒数。
javascript事件队列有优先权吗?
有点。 事件循环实际上由一个或多个事件队列组成。 在每个队列中,事件以FIFO顺序处理。
由浏览器决定要拥有多少队列以及为其提供哪种优先级形式。 单个事件队列没有Javascript接口或将事件发送到特定队列。
https://www.w3.org/TR/2014/REC-html5-20141028/webappapis.html#event-loops
每个任务都定义为来自特定任务源。 必须始终添加来自一个特定任务源并发往特定事件循环的所有任务(例如,由Document的计时器生成的回调,针对该Document的鼠标移动而触发的事件,排队等待该Document的解析器的任务)到同一个任务队列,但来自不同任务源的任务可以放在不同的任务队列中 。
例如,用户代理可以为鼠标和键事件(用户交互任务源)创建一个任务队列,为其他所有事件设置另一个任务队列。 然后,用户代理可以在四分之三的时间内为其他任务提供键盘和鼠标事件首选项,保持界面响应但不会使其他任务队列处于饥饿状态,并且从不处理来自任何一个任务源的事件。
FIFO。 真的没有什么可说的了。 你无法安排它。
当您查看可能同时发生的多个超时操作时,这可能会有点痛苦。 也就是说,如果您使用的是异步行为,则不应该依赖于它们的安排方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.