JavaScript 中的“事件循环”和“事件队列”是否相同?

0 html javascript css ecmascript-6

我是 JavaScript 新手,想知道“JS”如何处理异步操作。我开始知道它是在“事件循环”和“事件队列”的帮助下完成的,但我不知道其中的区别。有人可以帮我吗。

的一个例子asynchronous operations可以是:

function alpha(){
  setTimeout(() => alert("hi"), 3000);
};

alpha();
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 6

事件循环是浏览器(或其他 JavaScript 主机)运行的循环,从事件队列(更常见的是作业任务队列,列出等待处理的事件/作业/任务的队列)中拾取顶部项目并处理它,然后返回下一个并处理它,等等。

用伪代码术语来说(并且省略了很多细节):

// Event/job/task loop:
while (running) {
    const task = taskQueue.pop();
    if (task) {
        task();
    }
}
Run Code Online (Sandbox Code Playgroud)

JavaScript 代码或主机环境事件可能会将作业/任务添加到队列中,以便在循环到达它们时由循环拾取。

HTML 规范在此详细介绍了该过程。乍一看,在 HTML 规范中包含这些信息似乎很奇怪,但该规范不仅描述了 HTML(标记语言),还描述了用户代理(包括浏览器)应如何处理处理/呈现网页。

JavaScript 规范在这里讨论了这一点,尽管它没有详细说明主机应该执行哪种类型的循环,因为这是特定于主机的。

作为非浏览器 JavaScript 主机的示例,Node.js 文档在此处描述了其循环。


上面的伪代码中遗漏的更重要的细节之一是,几乎所有 JavaScript 主机中都至少有两个队列:主要队列(HTML 规范称为“任务队列”)和用于 Promise 反应的队列,以及可选的队列。其他东西(HTML 规范称为“微任务队列”)。所以这个工作循环看起来更像是:

// Event/job/task loop:
while (running) {
    const task = taskQueue.pop();
    if (task) {
        task();
        // Microtask loop:
        while (!microtaskQueue.isEmpty()) {
            const microtask = microtaskQueue.pop();
            microtask();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意微任务队列是如何在每个任务完成后清空的,这意味着如果任务队列中有任务 1、任务 2 和任务 3,并且在处理任务 1 的过程中将两个微任务添加到微任务队列中,则这些微任务会得到在任务 1 结束时、任务 2 之前运行。下面是一个示例:setTimeout将任务排队,但承诺反应(调用履行或拒绝处理程序)是微任务:

// Event/job/task loop:
while (running) {
    const task = taskQueue.pop();
    if (task) {
        task();
    }
}
Run Code Online (Sandbox Code Playgroud)
// Event/job/task loop:
while (running) {
    const task = taskQueue.pop();
    if (task) {
        task();
        // Microtask loop:
        while (!microtaskQueue.isEmpty()) {
            const microtask = microtaskQueue.pop();
            microtask();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)