Code前端首页关于Code前端联系我们

Javascript 事件循环的图示

terry 2年前 (2023-09-09) 阅读数 210 #Javascript
文章标签 JavaScript事件循环

Javascript 事件循环一开始让大多数开发人员感到有点困惑。

本文以低分辨率 GIF 进行直观解释,希望能帮助有需要的朋友。

但首先,什么是一系列事件以及为什么您应该关心?

JavaScript 是单线程的:一次只能运行一个任务。通常这不会是一个大问题,但现在想象一下您正在执行一个 30 秒的任务。

是的,对于这个任务,我们在做其他事情之前等待 30 秒(默认情况下,JavaScript 在主浏览器线程上运行,因此整个 UI 都关闭了)?现在是 2019 年,没有人想要一个缓慢且反应迟钝的网站。

幸运的是,浏览器为我们提供了一些 JavaScript 引擎本身没有的功能:Web API。这包括 DOM API、setTimeout、HTTP 请求等。这可以帮助我们创建异步、非阻塞行为。

当我们调用一个函数时,它会被添加到称为调用堆栈的东西中。调用堆栈是 JS 引擎的一部分,与浏览器无关。它是一个堆栈,意味着先进先出。当函数返回一个值时,它会从堆栈中弹出吗?

图解Javascript事件循环

响应函数返回setTimeout函数。 setTimeout 是由 Web API 提供给我们的:它允许我们在不阻塞主线程的情况下延迟任务。我们传递给 setTimeout 函数的回调函数 arrow function() => {return ‘Hey’} 已添加到 Web API 中。同时,setTimeout函数和response函数从病毒中弹出,并且都返回值!

图解Javascript事件循环在 Web API 中,计时器一直运行,直到我们传递给它的第二个参数 1000ms。回调不会立即添加到调用堆栈中,而是传递到队列中。

图解Javascript事件循环

这可能是一个令人困惑的部分:它并不意味着回调函数会在 1000 毫秒后添加到调用堆栈中(从而返回一个值)。它只是在 1000 毫秒后添加到队列中。但它是一个队列,函数必须等待轮到它!

现在是我们一直在等待的部分...是时候让事件循环完成其唯一的工作了:将队列连接到调用堆栈! 如果调用堆栈为空,则在所有先前调用的函数返回其值并从堆栈中弹出后,队列中的第一项将被添加到调用堆栈中。在这种情况下,不会调用其他函数,这意味着当回调函数成为队列中的第一项时,调用堆栈为空。

图解Javascript事件循环回调被添加到调用堆栈中,被调用,返回一个值,并弹出堆栈。

图解Javascript事件循环 阅读这篇文章很有趣,但只有一遍又一遍地阅读才会完全满意。尝试找出运行以下命令时登录到控制台的内容:

const foo = () => console.log("第一个");
const bar = () => setTimeout(() => console.log("第二次"), 500);
const baz = () => console.log("第三个");

酒吧();
foo();
baz();

你明白吗?让我们快速看一下在浏览器中运行此代码时会发生什么:

图解Javascript事件循环

  1. 我们调用bar,bar返回setTimeout函数。
  2. 传递给 SetTimeout 的回调被添加到 Web API,并且 setTimeout 函数和栏从调用堆栈中弹出。
  3. 当调用 foo 并打印 First 时,计时器就会运行。 foo 返回(未定义),调用 baz 并添加到回调队列中。
  4. baz 打印第三。事件循环看到baz返回后,调用堆栈为空,然后将回调添加到调用堆栈中。
  5. 回调是第二个打印的。

希望能帮助大家了解事件的循环!

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门