63. 浏览器里的 Event Loop
Posted 全端学堂
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了63. 浏览器里的 Event Loop相关的知识,希望对你有一定的参考价值。
Event Loop
表示事件循环,是指浏览器或 NodeJS
中避免 javascript
单线程运行时阻塞的一种机制,也就是异步的原理。浏览器和 NodeJS
基于不同的技术实现了各自的 Event Loop
,本文主要讨论浏览器中的 Event Loop
。
执行栈与任务队列
当一系列方法被调用时,因为 JavaScript
是单线程的,同一时间只能执行一个方法,因此 JavaScript
引擎提供一个被称为执行栈的结构来维护它们。
当第一次执行脚本时,JavaScript
引擎会解析代码,将其中的同步代码按照执行顺序放入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么 JavaScript
会向执行栈中添加这个方法的执行上下文环境(context
),随后进入这个执行上下文环境执行其中的代码,当这个执行上下文环境中的代码执行完毕并返回结果后,则退出这个执行环境并将其销毁,回到上一个方法的执行上下文环境中。这个过程反复进行,直到执行栈中的代码全部执行完毕。
当 JavaScript
引擎遇到一个异步任务后,由于 JavaScript
非阻塞的特点,它不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当异步任务返回结果后,JavaScript
会将这个任务加入与当前执行栈不同的另一个队列—任务队列(task queue
)。被放入任务队列不会立刻执行其回调,而是等待执行栈中的所有任务都执行完毕,当主线程处于闲置状态时,就会去查找任务队列是否有任务,如果有,那么主线程会从中取出排在第一位的任务,并把这个任务对应的回调函数放入执行栈中,然后执行其中的脚本,如此反复,这样就形成了一个无限的循环,将这个循环的过程称为“事件循环(Event Loop
)”。
这个过程大致如下图所示:
宏任务与微任务
上述事件循环过程是一个宏观的表述,实际上异步任务之间也并不相同,因此他们的执行优先级也有区别,上一节中我们介绍了宏任务(macrotask
)和微任务(microtask
),事件循环与它们也有关系。
我们说,事件循环中,异步任务返回结果后会被放到任务队列中,然而,根据这个异步任务的类型,实际上会被放入对应的宏任务队列或者微任务队列中去。在当前执行栈为空的时候,主线程会先查看微任务队列是否有任务存在,如果存在,则会依次执行微任务队列中各任务对应的回调函数,直到微任务队列为空,然后去宏任务队列中依次取出任务并将对应的回调函数加入执行栈中执行;如果不存在,那么直接去宏任务队列中取出一个任务并把对应的回调函数加入执行栈,如此反复。
当执行栈中脚本执行完毕时会先处理所有微任务队列中的任务,然后再去宏任务队列中取出任务执行。同一次事件循环中,微任务永远在宏任务之前执行。
以上是关于63. 浏览器里的 Event Loop的主要内容,如果未能解决你的问题,请参考以下文章