event loop 是异步回调的实现原理
js 代码的执行过程
- 从前到后,一行一行执行
- 如果某一行执行报错,则停止下面代码的执行
- 先把同步代码执行完,再执行异步
event loop 图解
以下方代码为例:
第1步 将第 1 行代码放入调用栈
将要执行第1行代码放入调用栈(call stack)中
第2步 执行第 1 行代码,清空调用栈
执行第1行代码,在浏览器中打印 Hi
,并清空调用栈
第3步 将第 3 行代码放入调用栈
第4步 执行第 3 行代码,设置定时器,清空调用栈
执行第3行代码,发现是一个定时任务,于是在 Web APIs 中设置一个回调函数为 cb 1 的定时器,清空调用栈
第5步 将第 7 行代码放入调用栈
第6步 执行第 7 行代码,清空调用栈,开始事件轮询
执行第7行代码,在浏览器中打印 Bye
,并清空调用栈
此时同步代码已执行完,开始事件轮询(即不断询问回调队列中是否存在可执行代码)
事件轮询会一直进行,直到整个js代码不再运行(如页面被销毁)。
第7步 将定时器的回调函数放入回调队列
本例中,第3行代码设置的定时器是 5 秒,则从第4步设置定时器开始记时,5秒后,将 Web APIS 中的定时器的回调函数放入回调队列(Callback Queue)中
第8步 事件轮询将定时器的回调函数放入调用栈
定时器的回调函数放入回调队列的那一刻,就会被事件轮询到(若回调队列已有多个回调函数,则会按先进先出的原则依次放入调用栈),并放入调用栈
第9步 将第 4 行代码放入调用栈
第10步 执行第 4 行代码,移除调用栈中的第 4 行代码
执行第4行代码,在浏览器中打印 cb1
,将第4行代码从调用栈中移除
第11步 清空调用栈,全部代码执行完毕
因回调函数 cb1内的代码已执行完毕,函数cb1 也被移出调用栈