漫谈 Event loop
Philip Roberts 在 JSConf EU 大会上分享了对 Event Loop 的理解,并写了一个可视化工具来展示 Event Loop 的过程。
Event Loop 中最重要的三个概念就是:任务队列,Web Api,调用栈。
调用栈
JS 是单线程的,意味着任意时刻都只有一个任务在执行。同步任务会按顺序进入执行栈。异步任务以队列形式排序等待进入执行栈。所有的异步任务都是在同步任务之后执行。
闭包
在执行 timeout 函数时,我们会发现内部的 log 函数会随后进入调用栈,当 log 函数出栈后 timeout 函数也随之出栈。若 timeout 内部存在一个执行完不能立即出栈的函数,例如一个定时器函数,或者一个被外部引用的内部函数。这个时候 timeout 也出不了栈,就形成了闭包。
任务队列
异步 I/O
在理解任务队列之前,我们先来看下什么是异步。
《UNIX网络编程卷1:套接字联网API(第3版)》 第六章第二小节中提到了 5 种 I/O 模型
- 阻塞式 I/O
- 非阻塞式 I/O
- I/O 复用
- 信号驱动式 I/O
- 异步 I/O
异步 I/O 不导致阻塞,从发起到等待数据到内存复制整个过程都是由内核去完成。待完成之后,内核再通知应用进程。
而从发起到完成整个过程中出现过阻塞行为的 I/O 就被称为同步 I/O。如图所示,除了异步 I/O 之外的 4 种 I/O 模型都被称为同步 I/O。
队列
队列是常见的数据结构之一,遵循先进先出的原则。当内核通知浏览器进程时,回调函数将进入任务队列,再按顺序进入调用栈执行。
WEB API
web api 可以理解为浏览器中非执行线程做的一些事。例如定时器,监听事件。
任务
宏任务代表一个个离散的、独立工作单元。而微任务指的是更小的任务。浏览器先执行一项宏任务,再执行微任务队列中的所有任务。再继续执行一项宏任务,以此循环。
参考资料
What the heck is the event loop anyway? | Philip Roberts | JSConf EU
- 调用栈
- 闭包
- 任务队列
- 异步 I/O
- 队列
- WEB API
- 任务
- 参考资料