当前位置: 首页 > 知识库问答 >
问题:

Javascript事件队列是否具有优先级?

闾丘鸣
2023-03-14

这些天,我阅读了一些关于setTimeoutsetInterval的文档。我了解到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 ms发生,Click事件处理程序fn2将在6ms发生,ajax回调fn3将在7ms发生,但所有三个函数都将被阻塞,直到for循环完成。在18ms,for循环完成,所以这些函数将被调用的顺序是什么。(fn1, fn2, fn3)或(fn2, fn3, fn1)

共有3个答案

单于亮
2023-03-14

先进先出。真的没什么可说的了。你不能安排它。

当您看到可能同时发生的多个超时操作时,这可能会有点麻烦。也就是说,如果你使用异步行为,你不应该依赖于它们是如何被调度的。

颜嘉福
2023-03-14

javascript事件队列有优先级吗?

差不多吧。事件循环实际上由一个或多个事件队列组成。在每个队列中,事件按 FIFO 顺序处理。

由浏览器决定要有多少队列,以及给它们什么形式的优先级。对于单个事件队列或向特定队列发送事件,没有Javascript接口。

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

每个任务都定义为来自特定的任务源。来自一个特定任务源并发往特定事件循环的所有任务(例如,由文档的计时器生成的回调,鼠标移动到该文档上而触发的事件,排队等待该文档解析器的任务)必须始终添加到同一任务队列中,但来自不同任务源的任务可以放置在不同的任务队列中。

例如,用户代理可以有一个用于鼠标和键事件的任务队列(用户交互任务源),另一个用于其他所有事件的任务队列。然后,用户代理可以在四分之三的时间内将键盘和鼠标事件优先于其他任务,保持界面响应但不使其他任务队列挨饿,并且永远不会无序地处理来自任何一个任务源的事件。

严峰
2023-03-14

为主 JavaScript 线程安排的工作将处理 FIFO。这包括来自各种异步任务(如 setTimeout 和 ajax 完成)的回调,以及事件处理程序。唯一的例外是,在主要的流行环境(浏览器和Node)中,本机 Promise 的分辨率回调会跳过队列(更准确地说,进入不同的更高优先级队列),有关详细信息,请参阅我的答案。

但撇开本机 promise 解析回调不谈:

但是所有三个函数都将被阻止,直到 for 循环完成。在 18ms 时,for 循环完成,因此调用这些函数的顺序是什么。(fn1,fn2,fn3) 或 (fn2,fn3,fn1)

你给 setTimeout 的时间是近似值,因为当这个时间到来时,JavaScript UI 线程可能正忙于做其他事情(如你所知);(newish)规范也有要求的最短时间,但它的执行程度因实现而异。同样,您不能保证单击事件将在 6 毫秒时排队,或者 ajax 完成将在正好在 7 毫秒处发生。

如果该代码开始,浏览器精确地执行了10ms,而< code>click事件恰好在6ms内排队,ajax请求恰好在7ms内完成,那么顺序将是:< code > fn2 (< code > click 处理程序)、< code > fn3 (Ajax完成)、< code > fn1 (< code > setTimeout ),因为这是它们排队的顺序。

但请注意,这些都是非常严格的时间安排。在实践中,我预计回调的排队顺序实际上是随机的,因为<code>单击

我认为这是一个更好的例子:

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

...其中,数字表示自脚本启动以来的毫秒数。

 类似资料:
  • 简介 举个例子。我有一个用户表,这个表根据用户名被Hash到不同的数据库实例上,我要找出这些用户中最热门的5个,怎么做?我是这么做的: 在每个数据库实例上找出最热门的5个 将每个数据库实例上的这5条数据按照热门程度排序,最后取出前5条 这个过程看似简单,但是你应用服务器上的代码要写不少。首先需要Query N个列表,加入到一个新列表中,排序,再取前5。这个过程不但代码繁琐,而且牵涉到多个列表,非常

  • 我正在使用std::priority\u队列和std::vector中的一些自定义对象。现在假设在调用top()函数时,有具有相同优先级的对象,我会按从最旧到最新的顺序获取它们。那么我的问题是,有没有可能改变这种行为,以便top()在优先级相同的情况下返回最近的对象?

  • 我需要建立一个队列,其中元素将在默认情况下按时间顺序添加和删除。但是,如果客户机为队列设置了优先级标志,我需要能够根据元素的优先级顺序提取元素。 我正在考虑创建一个优先级队列,它由一个映射支持,以优先级顺序跟踪队列索引,基于优先级标志,我可以从映射中提取项目,并从队列中弹出项目。 然而,对于这种方法,问题是,我是默认创建地图,还是只在设置了标志的情况下创建地图(考虑到创建动态地图的成本很高,我倾向

  • 我在Java使用PriorityQueue。 我有一个结构如下的对象: 优先考虑的是从最便宜到最贵的成本: 我使用add将对象包含在队列中。 它适用于队列中的每个元素,但我添加的最后一个元素总是位于底部。 我做错了什么?

  • 我有一个priority_queue,我想修改它的一些内容(优先级值),那么这个队列会被使用吗? 这取决于它是使用Push/Pop(更有可能,因为你只需要“插入”,而不是整个使用),还是访问top或Pop。 我很想更改队列中的一些元素。大概是这样的:

  • 是否有可用于 Haskell 的斐波那契堆/优先级队列?(甚至是渐近更好的?我在这个问题中找到了各种优先级队列实现的列表,但我找不到它们中的任何一个是否满足斐波那契堆的摊销运行时间: < li>Find-minimum是O(1)摊销时间。 < li >操作insert、decrease key和merge (union) work是O(1)摊销时间。 < li >操作删除和删除最小值是O(log