Skip to content
← back to home

What the heck is the event loop anyway? | Philip Roberts | JSConf EU

JSConf

youtube· 26:38standard

1.Introduction to the Event Loop

0:00 / 0:27

The speaker, Philip Roberts, introduces himself and the topic of the event loop in JavaScript. He shares his personal journey of understanding how JavaScript truly works beyond surface-level knowledge.

  • Event Loop
  • JavaScript

What's inside this course

  1. 0:00

    1. Introduction to the Event Loop

    The speaker, Philip Roberts, introduces himself and the topic of the event loop in JavaScript. He shares his personal journey of understanding how JavaScript truly works beyond surface-level knowledge.

  2. 0:27

    2. Initial Confusion and Key Terms

    Philip recounts his initial confusion with JavaScript's core concepts like V8, single-threaded nature, and callbacks. He lists several technical terms that often lead to misunderstanding for new developers.

  3. 1:42

    3. Understanding JavaScript's Environment

    Philip explains that V8 only handles memory allocation (heap) and the call stack. He reveals that common asynchronous features like setTimeout and DOM manipulation are not part of V8 itself, but are provided by the browser as 'Web APIs'.

  4. 3:58

    4. JavaScript's Single-Threaded Nature

    This chapter clarifies that JavaScript is single-threaded, meaning it has only one call stack and can execute only one piece of code at a time. This fundamental characteristic is crucial for understanding its concurrency model.

  5. 5:04

    5. Visualizing the Call Stack

    Philip uses a code example with `multiply`, `square`, and `printSquare` functions to visually demonstrate how the call stack works. Functions are pushed onto the stack when called and popped off when they return.

  6. 6:38

    6. Call Stack Errors and Memory Leaks

    The speaker illustrates how errors are reported with a full stack trace in the browser. He also explains how an infinitely recursive function can lead to a 'maximum call stack size exceeded' error, which is a form of memory leak.

  7. 8:00

    7. Understanding Blocking Operations

    Philip defines 'blocking' as any code that takes a long time to execute on the call stack, preventing other code from running. Examples include long loops, network requests, and image downloads.

  8. 9:20

    8. Synchronous AJAX Example

    Using a synchronous AJAX request as an example, Philip demonstrates how a slow operation can block the entire call stack. The program waits for each request to complete before moving to the next, leading to a frozen UI.

  9. 10:02

    9. Browser Blocking Demonstration

    A live demonstration shows how a blocking `while` loop freezes the browser UI, preventing any interaction or rendering. This highlights the critical problem that JavaScript's single-threaded nature poses for user experience.

  10. 11:00

    10. Introducing Asynchronous Callbacks

    To prevent blocking, JavaScript uses asynchronous callbacks. These functions are executed at a later time, allowing the main thread to remain free and the UI to stay responsive. This is a core concept for non-blocking operations.

  11. 11:50

    11. setTimeout Example with Call Stack

    Philip uses a `setTimeout` example to illustrate how asynchronous code works. The `setTimeout` callback is not immediately pushed to the call stack but is scheduled to run later, after the current synchronous code finishes.

  12. 12:50

    12. Browser's Role in Concurrency

    The speaker clarifies that while JavaScript is single-threaded, the browser provides Web APIs (like `setTimeout`, DOM, AJAX) that are effectively multi-threaded. These APIs handle concurrent operations outside the JavaScript runtime.

  13. 14:00

    13. Web APIs and the Callback Queue

    This chapter details how Web APIs interact with the callback queue. When an asynchronous operation (like `setTimeout`) completes, its callback is pushed onto the callback queue, waiting for the call stack to be empty.

  14. 15:50

    14. The Event Loop's Simple Job

    The event loop's primary function is explained: it continuously checks if the call stack is empty. If it is, the event loop takes the first callback from the callback queue and pushes it onto the call stack for execution.

  15. 17:00

    15. setTimeout(0) Explained

    The common pattern of `setTimeout(0)` is demystified. It doesn't execute immediately but rather pushes the callback to the queue, ensuring it runs after all current synchronous code on the call stack has completed.

  16. 18:20

    16. AJAX Request Flow with Event Loop

    Philip applies the event loop model to an AJAX request. The request is handled by Web APIs, and once completed, its callback is placed in the queue, eventually executed by the event loop when the stack is clear.

  17. 19:30

    17. Interactive Event Loop Visualization

    The speaker introduces 'Loupe', a tool he built to visualize the JavaScript runtime environment. He demonstrates how DOM events and `setTimeout` calls are processed through the Web APIs, callback queue, and event loop.

  18. 21:20

    18. setTimeout Delay is Minimum, Not Exact

    This chapter highlights that the delay specified in `setTimeout` is a minimum delay, not a guaranteed execution time. The callback will only run after the specified time AND when the call stack is empty, which might be later.

  19. 22:30

    19. Synchronous vs. Asynchronous Callbacks

    Philip distinguishes between synchronous callbacks (like those in `forEach`) and asynchronous callbacks. He demonstrates how to create an asynchronous `forEach` using `setTimeout(0)` to avoid blocking the main thread.

  20. 24:00

    20. Browser Rendering and the Event Loop

    The speaker explains that the browser tries to repaint the screen every 16.6ms (60fps) but is constrained by the JavaScript call stack. Rendering only occurs when the stack is clear, and it has a higher priority than other callbacks.

  21. 25:00

    21. Blocking Rendering with Synchronous Code

    A demonstration shows how a slow synchronous loop blocks browser rendering, making the UI unresponsive. This reinforces the importance of keeping the call stack clear to maintain a smooth user experience.

  22. 25:50

    22. Don't Block the Event Loop

    The core message is to avoid blocking the event loop by keeping the call stack clear of long-running synchronous tasks. This ensures the browser can perform necessary operations like rendering and responding to user input, creating a fluid UI.

Every chapter ends with a checkpoint (quiz, flashcards, retell, diagram, or prediction) and the course closes with a final boss-fight. More courses →

Transcript (253 segments)
0:02(Phillip Roberts)大家好,进来坐下吧。下午最后一个会议了。
0:07安静一下。演讲者是Phillip Roberts,他在苏格兰工作,专门从伦敦赶了过来。
0:13Phillip将要讲的是事件循环。
0:18请大家掌声欢迎菲利普
0:19大家好,非常感谢能到站台上演讲,这太棒了
0:21大家能允许我伸个懒腰吗,我需要舒展一下,这样我看起来没那么奇怪
0:28我想谈一下事件循环,事件循环究竟是什么东东
0:35作为JavaScript的事件循环。首先,就像他说的我在Andyet工作
0:43Andyet是美国一个很棒的小软件公司,如果你们需要帮助开发一些实时的应用,可以考虑我们
0:50那是我们擅长的东西。大约18个月前,我是一个专业的JavaScript开发者
0:58我开始考虑,JavaScript实际上是怎样运作的
1:06我没有完全了解。我听说过V8是Chrome里的JavaScript运行环境,但我不知道它是什么以及它做了什么
1:12我听说过单线程,还有很明显我在用回调函数。
1:17回调函数是怎么运作的?我开始去做了一些阅读,
1:23还在浏览器里做了一些试验,开始的时候大概是这样的。
1:26我当时的感受就是,JavaScript到底是什么?答案像这样:“JavaScript是一个单线程、非阻塞、异步、解释性脚本语言”
1:34是吧,非常酷。“我有一个调用栈,事件循环、
1:40回调队列和一些其他的API。” 好的,我并没有计算机科学学位
1:46我想说的是,这些名词,他们是专业名词。我听说过V8和其它的一些运行环境和不同的浏览器
1:51所以我想问问V8:“你是否有调用栈、事件循环、回调队列和其他API”
1:56“我有一个调用栈和堆 我不知道其他东西是什么“
2:00好吧,很有趣。那么,18个月过去了,我觉得我现在明白了
2:13(笑声)这些是我今天要和你们分享的东西。希望
2:17这能帮助接触JavaScript时间相对比较短的人理解为什么JavaScript这么怪异
2:23当你对比其他语言的时候,你可能会不理解为什么回调是个灾难但是还是被引入了
2:27如果你是个经验比较丰富的JavaScript开发者,希望能够
2:33让你对JavaScript的运行环境获得一些新的见解,使你可以对此考虑得更加周全
2:38那么如果我们看看JavaScript的运行环境。比如V8,V8是Chrome里的JavaScript运行环境
2:47这是一个JavaScript的运行环境示意图。堆记录了内存的分配
2:57然后是调用栈,这是帧这类东西所在的地方
3:04但是如果你克隆了V8的代码,然后
3:11搜索setTimeout或者DOM,HTTP请求这些东西的时候,它们并不在里面
3:18他们不存在于V8引擎,我对此大吃一惊,当你想要异步编程的时候,这些是你首先考虑要使用的东西
3:24但是它们并不存在于V8的源码里面?唔.. 很有趣。那么,这18个月的探索
3:32我开始意识到这是极其重要的部分
3:37我希望你们今天都能够理解这些部分是什么
3:42首先是V8运行环境,然后是浏览器提供的其他东西
3:47被称之为web APIs,DOM、AJAX、setTimeout之类的东西,再然后是神秘的
3:53事件循环和回调队列。我可以肯定你们事先听说过这些术语
3:58但是你们未必那么理解这些部分是怎么结合在一起的。那么,
4:03我将从解释这些术语开始,或许某些人并不了解,某些人或许知道。
4:08我们快速地过一遍,很明显有些人需要忍受一会
4:13但是我猜大部分人不会的。那么,JavaScript是一个单线程的编程语言
4:19单线程的运行环境,它有且只有一个调用栈,它每次只能够做一件事
4:25这是单线程的意思,程序每次只可以运行一段代码
4:31那么,让我们尝试对刚刚所说的内容可视化一下
4:35如果我有一些像在你们左边这样的代码,我们有一些函数
4:41一个将两个数字相乘的函数multiply,一个调用了前者的平方函数square
4:46一个打印函数printSquare,它调用了square,然后将结果用console.log打印出来
4:51然后在最后我们调用了printSquare。这些代码看起来都没问题吧
4:56好的,那么,我们运行它。调用栈基本上
5:04是一个记录当前程序所在位置的数据结构,如果当前进入了
5:09某个函数,这个函数就会被放在栈里面。如果当前离开了某个函数
5:13这个函数就会被弹出栈外,这是栈所做的事。如果你运行这个文件
5:19将会有一个类似main的函数,它指代文件自身,我们首先把它放进栈
5:23然后,我们从上而下查看声明了的函数
5:28最后是printSquare,好了,我们知道了printSquare被调用了,那么我们
5:33把它推进栈里,然后它调用了square,所以也把它推进栈里
5:38square也调用了multiply,同样也把它推进栈。最后我们得到了multiply的返回值
5:44我们把multiply弹出栈,然后square也得到了返回值,再把square弹出栈
5:49最后到printSquare,它调用了console.log,到这里已经没有返回值了
5:57我们到了函数的最后部分,然后我们完成了。这就是一个可视化的调用栈
6:02这能够理解吗?(是的,Phil)很好,那么如果你以前没了解过调用栈
6:10现在你知道了,当你在浏览器端做网站开发的时候
6:15如果在Chorme运行这样的代码,baz函数调用了bar函数,bar函数调用了foo函数
6:20foo函数抛出一个错误,我们看到会是这样的
6:29它将整个栈树都打印了出来,错误从foo开始,到bar, 到baz,到匿名函数
6:38也就是我们说的main函数。同样地,如果你听说过像内存泄露这类名词
6:45这就是其中一个例子,如果我们有一个调用自身的函数foo,那么会发生什么
6:52我们有一个函数调用了foo,foo又调用了foo,如此一直下去
6:59最后Chrome会说,“你可能并不是想要调用它自己16,000次”
7:05“我为你终止了它,这样你可以找到bug在哪里。” 好的
7:11我可能向你们呈现了一个调用栈,可能你在开发的时候就已经注意到了
7:17那么,现在有了一些更大的难题。
7:23什么使程序运行变慢?所以我们谈谈阻塞
7:30没有严格的定义说什么是阻塞,什么不阻塞。仅仅是指代码运行得很慢
7:36比如说,console.log不慢,遍历从1到10亿很慢,网络请求很慢
7:41下载图片也很慢。反正在栈里表现很慢的东西都叫阻塞。
7:49这里有一个小例子,比如说我们有这样一些伪码
7:57就像jQuery的AJAX请求
8:05如果你没给AJAX请求加上回调函数,它们会是同步的
8:10如果我们运行它,首先调用了getSync,然后我们在等待.. 因为
8:16我们在做网络请求,网络请求相对于计算机本地来说很慢,那么
8:22等请求完成了,我们才继续。然后是继续等,再继续。我想说的是
8:33这些请求可能永远也不会结束,那么.. 好的我等不及要回家了。终于结束了
8:39当这些所有都跑一遍,栈才会被清空。那么如果一个编程语言是单线程的
8:46比如ruby,刚才的状况就会发生。好的,我们
8:51来请求一个资源,我们就要干巴巴地等着请求完成,因为没有办法了
8:56那这有什么问题呢?问题是我们的代码是要跑在浏览器上的
9:04那么,我们开始了... 好了,这是Chrome
9:13这是刚才运行的代码
9:19我用一个while循环伪造了这一点, 因为它是同步的,要
9:24循环环五秒钟,我才能继续, 如果在这里打开控制台。我们可以看到
9:34会发生什么,正在请求foo.com,为什么 发生这种情况,我不能做任何事情,对不对,
9:41即使是运行按钮也尚未完成重新渲染 当我点击它。浏览器被
9:45阻塞了,它卡住了,它不能做任何事情 直到这些请求完成。然后将所有
9:52的东西蹦出来了,因为我之前做了一些操作,它明白我已经完成了,但它并不能
9:56实际地渲染。它不能做任何事情。 那是因为如果调用栈有东西
10:04然后是这儿。是的,它还在运行。我们已经弄清了同步请求,
10:11浏览器现在不能做别的事情。它不能 渲染,它不能运行任何其他代码,它
10:16卡住了。并不出乎意料,对吧.如果我们希望人们 拥有漂亮流畅的用户界面,我们就不能阻塞
10:20调用栈。那么,我们应该如何处理呢?我们最简单的方式是提供异步回调
10:28在浏览器中几乎没有阻塞的函数 ,node里也是这样,他们都
10:35是异步函数,这基本上意味着我们 运行一些代码,给它一个回调函数
10:40并在之后运行,如果你看过JavaScript代码你就会看过这些异步回调,这
10:45实际上是什么样的呢。这里有些简单的例子来提示我们到底运行到哪了。像这样的代码,console.log输出
10:53Hi,对吧。我们运行setTimeout,但 我们把console.log放到队列里在以后再运行, 所以我们跳过
11:00并运行 JSConf 这里,然后5秒钟之后,我们输出“there”,对吧。理解了?开心。基本上
11:08这是的setTimeout做的事情。所以, 异步回调与问候到
11:13我们以前看到烟囱......如何工作的呢? 让我们来运行代码。 CONSOLE.LOG喜。 setTimeout的。
11:23我们知道,它不会立即运行,我们就知道 它会在五秒钟的时间运行,我们
11:28不能推到堆栈中,不知何故, 刚刚消失后,我们没有像的方式
11:34的描述此,但我们会来 它。我们登录JSConfEU,清晰,5秒钟后
11:41不知何故神奇地“存在”出现在堆栈中。 如何发生的?这就是 - 这
11:49基本上是,其中事件循环进来 对并发性。对,所以我一直有种
11:56部分躺在你并告诉你, JavaScript的只能做一件事情在同一时间。
12:00这是真正的JavaScript的运行时只能 做一件事情在同一时间。它不能使一个
12:04AJAX请求,而你正在做的其他代码。 而你正在做它不能做的setTimeout
12:09另一个代码。我们可以做的事情的原因 同时是浏览器是多
12:13刚运行时。所以,请记住这个图, JavaScript的运行时可以做的一件事
12:19一时间,但浏览器给了我们这些其他 的事情,给我们这些我们要的API,这些
12:23是有效的线程,你可以只是使 调用和浏览器的那件
12:30都知道在这个并发踢。如果 你后端此人长相图
12:35基本相同的节点,而不是网络 我们的API有C ++ API和线程是
12:42由C ++从你被隐藏。现在我们有 这张照片让我们看看如何运行此代码
12:51在浏览器的外观更饱满的画面 喜欢。因此,和以前一样,运行代码,控制台
12:58登录喜,喜登录到控制台,简洁。现在 我们可以看到,当我们称之为setTimeout的会发生什么。
13:05我们 - 我们通过这个回调函数 和延迟,setTimeout调用。现在的setTimeout
13:13是一个API浏览器提供给我们,它 不生活在V8的来源,这是多余的
13:18我们的东西 得到我们正在运行中的JavaScript运行
13:23时间。浏览器揭开序幕的计时器 您。现在,它要处理数
13:30下来你的,正确的,所以这就意味着我们的setTimeout 打电话,本身现在已经完成,所以我们可以弹出
13:35堆栈。 “JSConfEU”,清楚,所以, 现在我们已经有了这个定时器在Web API,它
13:455秒钟后将会完成。现在 网络API不能只是开始修改你的
13:51码,它不能夹头东西到堆栈 当它准备,如果它没它会出现
13:55随机在你的代码的中间所以这 就是任务队列或回调队列
14:00踢,任何网络的API推回调 到任务队列时,它的完成。最后
14:08我们得到的事件循环,演讲的题目, 到底是什么事件循环就像
14:13最简单的一种小片在这整个方程, 而且它有一个非常简单的工作。
14:19该事件循环的工作就是看堆栈 并期待在任务队列。如果堆栈
14:23空它需要在队列的第一件事 并推动它上到堆栈从而有效地
14:28运行。所以在这里我们可以看到,现在的堆栈 显然,有一个在任务队列的回调,
14:34事件循环运行时,它说,哦,我去 做一些事情,推到回调
14:40堆叠。请记住它的堆栈如JavaScript 土地,回到屋里V8,将出现回调
14:45在堆栈上运行,执行console.log“那里”, 我们就大功告成了。那有意义吗?大家
14:53我在哪里?真棒!好的。所以,现在我们可以看到 这是如何工作有可能是第一个
15:00交锋你曾与异步的东西 这对于一些奇怪的原因,有人说称
15:04你要调用的setTimeout零, - 好吧,你要我跑零功能
15:11时间?为什么我会它包装在一个setTimeout的? 第一次像你穿越这片运行,如果
15:15你和我一样,我看到它在做什么,但 我不知道为什么。其原因是,一般地,
15:22如果你想推迟到的东西 堆栈是明确的。所以我们知道在看
15:27这一点,如果你写的JavaScript,那我们 将看到同样的结果,我们要
15:30看“喜”,“JSConf”和“那里” 将要出现在末端。我们可以看到
15:36如何出现这种情况。该setTimeout的零,现在 它会立即推完成
15:42它到队列中,请记住我说过 事件循环,它必须等待直到堆栈
15:46很清楚,才可以推回调 堆栈,所以你的堆栈将继续
15:51运行,执行console.log“喜”,“JSConfEU” 和明确的,现在事件循环可以踢
15:58并调用回调函数。这就像一个例子 的setTimeout零的,被延迟了执行
16:06的代码,无论出于何种原因,以结束时 堆栈。或者直到堆栈是明确的。好的。
16:15因此,所有这些Web API的工作方式相同, 如果我们有AJAX请求,我们做一个AJAX请求
16:21用一个回调的URL,工作原理相同 这样,哎呀对不起,控制台日志,“喜”,使
16:28一个AJAX请求,运行该代码 AJAX请求不生活在JavaScript运行
16:33但在浏览器中的Web API,所以我们旋转 它与在URL中的回调,你的代码
16:40可以继续运行。在此之前,XHR请求 完成后,或者它可能永远不会完全,这是
16:46还好,堆栈可以继续运行,假设 它完成后,被推到队列中,挑
16:51同比事件循环,它的运行。这是 一切发生在一个异步调用发生。
16:58让我们做一个疯狂的复杂的例子,我希望 此去上班,如果你还没有意识到
17:06这一切都是在主题有像我这样做不 知道在这整个甲板500动画步骤。
17:12(代码炸毁,火焰动画)(掌声) Ĵ嗯...没有...所以...有趣,我们
17:35给个链接。嗯...这是足够大的, 其他人会看到?好了,所以基本上我写的
17:44这次谈话苏格兰JS,以后再说 我打破了幻灯片的一半,不能
17:53不屑于重做所有的幻灯片,因为它 在主题演讲中的屁股共苦
17:57做到这一点,所以我把容易得多路线(笑) 写作一个工具,可以可视化的JavaScript
18:07运行时环境在运行时,它被称为循环。 所以,让我们只要运行这​​个例子,并且其中
18:15是那种,我们必须在这个例子中 上一张幻灯片,我还没有匀XHR然而,
18:21它是可行的我只是还没有这样做。正如你 可以看到代码,我们要记录的东西,
18:26这是周围的addEventListener,setTimeout的垫片 而我们要做一个的console.log。 -
18:34我要运行它,看看会发生什么等等 ...添加DOM API,添加一个超时,代码
18:40要继续运行,推回调 在其中运行,我们就大功告成了队列中。
18:49如果我点击这里,那么它会触发... 网络API,排队点击回调
18:55并运行它。如果我咯咯叫百倍我们 可以看看会发生什么。我点击,点击
19:02没有得到立即处理,本身 被推到队列,如队列获取
19:06处理后,最终我的点击是要 得到处理了,对吧。所以,我有几个
19:13例如我要通过这里跑。这里 我们走了,好了,所以,我只是要通过运行
19:25几个例子只是一种说说 你可能已经在运行,有几件事
19:31并没有想过与异步的API,在 这个例子中我们称之为setTimeout的四倍
19:37与所述一个第二延迟,和的console.log “喜”。由当时的回调得到排队...
19:50这第四个回调,我们要求一秒钟 延迟,它仍然在等待,回调
19:54还没有运行,对吧。
19:57这说明了 - 像什么时间 出究竟是干什么,这不是一个保证
20:02时间执行,这是一个最短时间 执行,就像setTimeout的零不
20:07立即运行代码,它运行的代码 接下来十岁上下,有时,对不对?所以......在这
20:17例如,我想谈谈回调,因此, 取决于谁,说话以及如何短语
20:26东西,回调可能是两件事情之一, 回调可以是任何函数,另一
20:30函数调用或回调可以更明确地 异步回调作为一个将
20:36得到在被推回回调队列 未来。这段代码说明了差异,
20:42对。在阵列上在foreach方法,它 不会运行,它需要一个函数,这你
20:48可以调用回调,但它没有运行 它以异步方式,它的运行它内
20:53当前堆栈。我们可以定义异步 的forEach所以它可以采取的阵列,一个回调
21:02和用于阵列中的每个项目它将会 做一个零的setTimeout与回调,
21:07我想这应该传递的价值,但 任何方式,所以,我要运行它,我们可以
21:13看到有什么区别,所以对于第一 中运行代码块,它要坐
21:18并阻断栈,对不对?直到它的完成, 而在异步版本,好吧,这减缓
21:26下来,但是我们基本上要排队一个 一堆回调和他们将清除
21:31然后我们就可以实际运行通过并做 一个的console.log。在这个例子中的console.log
21:37速度快,所以这样做的好处异步 是不是很明显,但让我们说你做
21:41在每一个元素上的一些处理缓慢 数组。我觉得我有什么地方显示
21:52不,不,我不知道。好的。所以我们说 - 哎呀。所以我有一个延时功能是
22:02只是缓慢的,它只是一个缓慢的事情。所以...我们 说处理异步这里处理同步。
22:15好了,现在,我要打开我有一件事 今天上午,从字面上一起砍死其中
22:24是模拟重绘或渲染 浏览器,这是我没有触及
22:28是怎么回事呢,这跟渲染互动 - 我有种感动就可以了,但没有真正
22:35解释它。因此,基本上该浏览器是 通过你在做什么的javaScript样的制约,
22:42浏览器想重绘屏幕 每16.6毫秒,60帧秒
22:48是理想的,这是它会做重绘最快 如果可以。但它是由你在做什么约束
22:54这样做在JavaScript中由于种种原因,所以 它实际上并没有进行渲染,如果有
23:00在栈上的代码,对吧。像渲染 一种叫几乎就像在回调
23:05本身。它要等到堆栈是明确的。 不同的是,在呈现给定
23:11比你的回调更高的优先级,每 16毫秒它要排队一个分割,
23:19等到堆栈前它可以很清楚 其实这样做渲染。因此,这是 -
23:25这种渲染队列只是模拟渲染, 每一秒这是我可以做一个呈现?是,
23:29我可以做一个呈现?是。其中,因为我们 代码是不是现在做任何事情。如果我运行
23:33代码,你可以看到,而我们正在做这种缓慢 通过阵列的同步环,我们的渲染
23:41被阻塞,右,如果我们的渲染被阻止 你不能在屏幕上选择文本,你不能
23:46点击东西,看到响应,右, 像比如我之前展示。在这
23:52例如,好吧,这虽然我们排队堵塞 了异步超时,即比较快
24:00但我们给定的 - 我们种给 渲染每一个元素,因为之间的机会
24:05我们已经排队它异步跳 在那里,做渲染,这是否
24:13感?
24:13>>是的 >>是的,很酷。所以,这只是一种 -
24:16这就像是怎样的一个模拟 渲染的作品,但它只是真正体现出
24:20你当人们说不要阻塞事件 循环,这正是他们在说什么
24:24关于。他们说不要放低劣慢 堆栈,因为当你这样做的代码
24:28浏览器不能做什么它需要做的, 创建一个漂亮的流体UI。这就是为什么当你
24:34做这样的事情的图像处理或动画效果 如果你没有太多的东西变得呆滞
24:40小心你如何排队的代码。 所以这方面的一个例子,我们可以用看
24:48滚动处理程序 - 这样滚动柄 - 就像在DOM滚动事件引发了不少,
24:56没错,他们喜欢触发 - 我相信 他们喜欢触发每16每一帧
25:02毫秒,如果我有这样的代码 对。在document.scroll,动画的东西,
25:08或者做一些工作。如果我有这样的代码,例如 我滚动它要排队像
25:15吨回调权。然后它有 经过并处理所有​​这些和各
25:21这些的加工很慢的话, 好吧,你不堵栈,你
25:26充斥队列排队的事件。所以, 这就像刚刚帮助可视化,我猜,
25:34当你真正触发所有会发生什么 这些回调,还有的办法可以抖
25:38这从根本上说,没关系,我们要 排队所有这些事件,但让我们做的
25:44缓慢的工作,直到用户每隔几秒钟或 停止滚动时间我一定量
25:55认为这基本上它。有一个整体 其他的谈话在地狱这是如何工作的。因为
26:04基本上都在运行的代码,这样的代码 运行在运行时,正确的,而且它减慢
26:10由我通过一个Esprima一个JavaScript运行 解析器,我插入一个大循环的同时,也需要
26:18半秒,它只是缓慢运动的代码。 运到网络工作者,并做了一大堆
26:25东西形象化发生了什么事,而 在运行时是有道理这样做。整个
26:31其他的谈话在。我超级兴奋 它之后会跟任何人谈起它
26:38因为我认为这是一种整齐,所以用 即,非常感谢(掌声)