awesome-interview/book3/browser-event-loop/index.html

19 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-beta.5">
<link rel="search" type="application/opensearchdescription+xml" title="HZFE - 剑指前端 Offer" href="/awesome-interview/opensearch.xml">
<link rel="preconnect" href="https://hm.baidu.com">
<script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?c7cd0fd77ac518cc6ef46461cdc9524b";var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(e,c)}()</script><title data-react-helmet="true">浏览器事件循环 | HZFE - 剑指前端 Offer</title><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:url" content="https://hzfe.github.io/awesome-interview/book3/browser-event-loop"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="current"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-react-helmet="true" property="og:title" content="浏览器事件循环 | HZFE - 剑指前端 Offer"><meta data-react-helmet="true" name="description" content="相关问题"><meta data-react-helmet="true" property="og:description" content="相关问题"><link data-react-helmet="true" rel="shortcut icon" href="/awesome-interview/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://hzfe.github.io/awesome-interview/book3/browser-event-loop"><link data-react-helmet="true" rel="alternate" href="https://hzfe.github.io/awesome-interview/book3/browser-event-loop" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://hzfe.github.io/awesome-interview/book3/browser-event-loop" hreflang="x-default"><link data-react-helmet="true" rel="preconnect" href="https://61YWQXP6JY-dsn.algolia.net" crossorigin="anonymous"><link rel="stylesheet" href="/awesome-interview/assets/css/styles.304d13b7.css">
<link rel="preload" href="/awesome-interview/assets/js/runtime~main.50b7dd91.js" as="script">
<link rel="preload" href="/awesome-interview/assets/js/main.178fbfc5.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<div><a href="#" class="skipToContent_1oUP">Skip to main content</a></div><nav class="navbar navbar--fixed-top navbarHideable_2qcr"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><b class="navbar__title">剑指前端 Offer</b></a></div><div class="navbar__items navbar__items--right"><a href="https://github.com/hzfe/awesome-interview" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link"><span>GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_3J9K"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a><div class="searchBox_1Doo"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper docs-doc-page"><div class="docPage_31aa"><button class="clean-btn backToTopButton_35hR" type="button"><svg viewBox="0 0 24 24" width="28"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="currentColor"></path></svg></button><aside class="docSidebarContainer_3Kbt"><div class="sidebar_15mo sidebarWithHideableNavbar_267A"><a tabindex="-1" class="sidebarLogo_3h0W" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--light_3UqQ"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--dark_hz6m"><b>剑指前端 Offer</b></a><nav class="menu thin-scrollbar menu_Bmed menuWithAnnouncementBar_2WvA"><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" href="/awesome-interview/about">关于我们</a></li><li class="menu__list-item"><a class="menu__link" href="/awesome-interview/">前言</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题一</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题二</a></li><li class="menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#">模拟题三</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/awesome-interview/book3/browser-event-loop">浏览器:浏览器事件循环</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/browser-memory-leaks">浏览器:如何定位内存泄露</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/engineer-webpack-loader">工程化:谈下 webpack loader 的机制</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/frame-react-hooks">框架React Hooks 实现原理</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/frame-diff">框架:常见框架的 Diff 算法</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/js-async">基础JavaScript 异步编程</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/js-ts-interface-type">基础TypeScript 中的 Interface 和 Type Alias</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/css-mobile-adaptive">样式:移动端自适应的常见手段</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/network-http-1-2">网络HTTP2 和 HTTP1.1 的对比</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/coding-arr-to-tree">编码:将列表还原为树状结构</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/algorithm-binary-tree-k">算法:二叉搜索树的第 k 个结点</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/topic-white-screen-optimization">综合:如何减少白屏的时间</a></li></ul></li></ul></nav><button type="button" title="Collapse sidebar" aria-label="Collapse sidebar" class="button button--secondary button--outline collapseSidebarButton_1CGd"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_3E-R"><g fill="#7a7a7a"><path d="M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"></path><path d="M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"></path></g></svg></button></div></aside><main class="docMainContainer_3ufF"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_3FnS"><div class="docItemContainer_33ec"><article><div class="tocCollapsible_1PrD tocMobile_3Hoh"><button type="button" class="clean-btn tocCollapsibleButton_2O1e">On this page</button></div><div class="markdown"><header><h1>浏览器事件循环</h1></header><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="相关问题"></a>相关问题<a class="hash-link" href="#相关问题" title="Direct link to heading">#</a></h2><ul><li>什么是浏览器事件循环</li><li>浏览器为什么需要事件循环</li><li>Node.js 中的事件循环</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="回答关键点"></a>回答关键点<a class="hash-link" href="#回答关键点" title="Direct link to heading">#</a></h2><p><code>任务队列</code> <code>异步</code> <code>非阻塞</code></p><p>浏览器需要事件循环来协调事件、用户操作、脚本执行、渲染、网络请求等。通过事件循环,浏览器可以利用<strong>任务队列</strong>来管理任务,让异步事件<strong>非阻塞</strong>地执行。每个客户端对应的事件循环是相对独立的。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="知识点深入"></a>知识点深入<a class="hash-link" href="#知识点深入" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="1-什么是浏览器事件循环"></a>1. 什么是浏览器事件循环<a class="hash-link" href="#1-什么是浏览器事件循环" title="Direct link to heading">#</a></h3><blockquote><p>在计算机中Event Loop 是一个程序结构,用于等待和发送消息和事件。 —— 维基百科</p></blockquote><p>Event Loop 可以理解为一个消息分发器,通过接收和分发不同类型的消息,让执行程序的事件调度更加合理。</p><p><strong>浏览器事件循环是以浏览器为宿主环境实现的事件调度</strong>,操作顺序如下:</p><ol><li>执行同步代码。</li><li>执行一个宏任务(执行栈中没有就从任务队列中获取)。</li><li>执行过程中如果遇到微任务,就将它添加到微任务的任务队列中。</li><li>宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)。</li><li>当前宏任务执行完毕,开始检查渲染,然后渲染线程接管进行渲染。</li><li>渲染完毕后JavaScript 线程继续接管,开始下一个循环。</li></ol><p>下图展示了这个过程:</p><p><img src="https://user-images.githubusercontent.com/12165373/129468098-f75d76f6-ad01-4390-a155-7fcd179f6a07.gif" alt="browser event loop"></p><blockquote><p>图片来源 <a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ&amp;t=31s" target="_blank" rel="noopener noreferrer">JS CONF EU 2014</a></p></blockquote><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="2-浏览器为什么需要事件循环"></a>2. 浏览器为什么需要事件循环<a class="hash-link" href="#2-浏览器为什么需要事件循环" title="Direct link to heading">#</a></h3><p>由于 JavaScript 是单线程的,且 JavaScript 主线程和渲染线程互斥,如果异步操作(如上图提到的 WebAPIs阻塞 JavaScript 的执行会造成浏览器假死。而事件循环为浏览器引入了任务队列task queue使得异步任务可以非阻塞地进行。</p><p>浏览器事件循环在处理异步任务时不会一直等待其返回结果,而是将这个事件挂起,继续执行栈中的其他任务。当异步事件返回结果,将它放到任务队列中,被放入任务队列不会立刻执行回调,而是等待当前执行栈中所有任务都执行完毕,主线程处于空闲状态,主线程会去查找任务队列中是否有任务,如果有,取出排在第一位的事件,并把这个事件对应的回调放到执行栈中,执行其中的同步代码。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="3-宏任务与微任务"></a>3. 宏任务与微任务<a class="hash-link" href="#3-宏任务与微任务" title="Direct link to heading">#</a></h3><p>异步任务被分为两类宏任务macrotask与微任务microtask两者的执行优先级也有所区别。</p><p>宏任务主要包含script整体代码、setTimeout、setInterval、setImmediate、I/O、UI 交互事件。</p><p>微任务主要包含Promise、MutationObserver 等。</p><p>在当前执行栈为空的时候,主线程会查看微任务队列是否有事件存在。如果不存在,那么再去宏任务队列中取出一个事件并把对应的回调加入当前执行栈;如果存在,则会依次执行队列中事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的一个事件,把对应的回调加入当前执行栈。如此反复,进入循环。下面通过一个具体的例子来进行分析:</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly js"><pre tabindex="0" class="prism-code language-js codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 微任务1</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;Promise1&quot;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 宏任务2</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;setTimeout2&quot;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 宏任务1</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;setTimeout1&quot;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 微任务2</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;Promise2&quot;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>最后输出顺序为Promise1setTimeout1Promise2setTimeout2。具体流程如下</p><ol><li>同步任务执行完毕。微任务 1 进入微任务队列,宏任务 1 进入宏任务队列。</li><li>查看微任务队列,微任务 1 执行,打印 Promise1生成宏任务 2进入宏任务队列。</li><li>查看宏任务队列,宏任务 1 执行,打印 setTimeout1生成微任务 2进入微任务队列。</li><li>查看微任务队列,微任务 2 执行,打印 Promise2。</li><li>查看宏任务队列,宏任务 2 执行,打印 setTimeout2。</li></ol><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="4-nodejs-中的事件循环"></a>4. Node.js 中的事件循环<a class="hash-link" href="#4-nodejs-中的事件循环" title="Direct link to heading">#</a></h3><p>在 Node.js 中,事件循环表现出的状态与浏览器中大致相同。不同的是 Node.js 中有一套自己的模型。 Node.js 中事件循环的实现是依靠的 libuv 引擎。下图简要介绍了事件循环操作顺序:</p><p><img src="https://user-images.githubusercontent.com/12165373/129439935-105a2439-23c8-4b2c-aea1-2493c3bf50e9.png" alt="node event loop"></p><blockquote><p>图片来源 <a href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop" target="_blank" rel="noopener noreferrer">Node.js 官网</a></p></blockquote><ol><li>timers本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。</li><li>pending callbacks执行延迟到下一个循环迭代的 I/O 回调。</li><li>idle、prepare仅系统内部使用。</li><li>poll检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞。</li><li>checksetImmediate() 回调函数在这里执行。</li><li>close callbacks一些关闭的回调函数socket.on(&#x27;close&#x27;, ...)。</li></ol><p>在每次运行的事件循环之间Node.js 检查它是否在等待任何异步 I/O 或计时器,如果没有的话,则完全关闭。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="参考资料"></a>参考资料<a class="hash-link" href="#参考资料" title="Direct link to heading">#</a></h2><ol><li><a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loops" target="_blank" rel="noopener noreferrer">whatwg event loops</a></li><li><a href="https://en.wikipedia.org/wiki/Event_loop" target="_blank" rel="noopener noreferrer">wikipedia event loops</a></li><li><a href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop" target="_blank" rel="noopener noreferrer">Node.js event loops</a></li></ol></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/awesome-interview/book2/topic-multi-pics-site-optimize"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« 综合:多图站点性能优化</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/awesome-interview/book3/browser-memory-leaks"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">浏览器:如何定位内存泄露 »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_35-E thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#相关问题" class="table-of-contents__link">相关问题</a></li><li><a href="#回答关键点" class="table-of-contents__link">回答关键点</a></li><li><a href="#知识点深入" class="table-of-contents__link">知识点深入</a><ul><li><a href="#1-什么是浏览器事件循环" class="table-of-contents__link">1. 什么是浏览器事件循环</a></li><li><a href="#2-浏览器为什么需要事件循环" class="table-of-contents__link">2. 浏览器为什么需要事件循环</a></li><li><a href="#3-宏任务与微任务" class="table-of-contents__link">3. 宏任务与微任务</a></li><li><a href="#4-nodejs-中的事件循环" class="table-of-contents__link">4. Node.js 中的事件循环</a></li></ul></li><li><a href="#参考资料" class="table-of-contents__link">参考资料</a></li></ul></div></div></div><div class="row"><div class="col"><div class="react-utterences"><div>Loading script...</div></div></div><div class="col col--3"></div></div></div></main></div></div></div>
<script src="/awesome-interview/assets/js/runtime~main.50b7dd91.js"></script>
<script src="/awesome-interview/assets/js/main.178fbfc5.js"></script>
</body>
</html>