title: JavaScript中的事件循环&消息队列
作为一门设计初衷为了处理浏览器网页交互(DOM
操作、UI
动画等)的语言,JavaScript
只能被设计为单线程(否则多个线程同时处理DOM
那将会造成混乱)。
可是写过JavaScript
代码的人都用过定时器、ajax
、事件绑定等。如果是单线程那岂不是无法完成这些异步请求?
一. 前言
其实,JavaScript
单线程指的是浏览器中负责解释和执行JavaScript
代码的只有一个线程——**JavaScript
引擎线程。**除了他之外浏览器还有其他四个线程:
- 事件触发线程
- 定时器触发线程
- 异步
http
请求线程 GUI
渲染线程
当遇到计时器、DOM事件监听或是网络请求时,JS
引擎会将其交给webapi
,也就是浏览器提供的相应线程。而JS引擎则继续后边的其他任务,以此方式实现异步非阻塞。
在此咱们不得不讲一下setTimeout
(setInterval
)函数。这东西没咱们想象的那么准,原因就在于当事件结束后他会将相应的回调函数(callback
)交还给 消息队列。而消息队列中排列着其他的任务,只有轮到它才会被执行。所以setTimeout
只能保证其在ms
毫秒 之后 执行。
二. 事件循环与消息队列
2.1 什么是消息队列
众所周知JavaScript
中的存储区域分为堆区、栈区、还有消息队列区。
- 堆区存放用户创建的对象。(内训泄露定位的主要区域也在这里。)
- 栈区则是用来处理函数执行(所以又称为执行栈)。每嵌套一层向栈中推入函数信息,得到返回值后出栈。主代码块依次进入执行栈,依次执行。
- 而消息队列则是用来处理异步任务。每当出现异步调用事件时都会将其入队,执行完毕后再由任务队列通知主线程,让
JS
引擎接管此事件。