const foo = () => console.log('First')
const bar = () => setTimeout(() => console.log('Second'))
const baz = () => console.log('Third')
bar()
foo()
baz()
我们有一个 setTimeout
函数,并首先调用它。然而,它是最后打印日志的。
这是因为在浏览器中,我们不仅有运行时引擎,还有一个叫做 WebAPI
的东西。WebAPI
提供了 setTimeout
函数,也包含其他的,例如 DOM。
将 callback 推送到 WebAPI 后,setTimeout
函数本身(但不是回调!)将从栈中弹出。
<img src="https://i.imgur.com/X5wsHOg.png" width="200">
现在,foo
被调用,打印 "First"
。
<img src="https://i.imgur.com/Pvc0dGq.png" width="200">
foo
从栈中弹出,baz
被调用. 打印 "Third"
。
<img src="https://i.imgur.com/WhA2bCP.png" width="200">
WebAPI 不能随时向栈内添加内容。相反,它将回调函数推到名为 queue 的地方。
<img src="https://i.imgur.com/NSnDZmU.png" width="200">
这就是事件循环开始工作的地方。一个事件循环查看栈和任务队列。如果栈是空的,它接受队列上的第一个元素并将其推入栈。
<img src="https://i.imgur.com/uyiScAI.png" width="200">
bar
被调用,打印 "Second"
,然后它被栈弹出。