- Published on
事件循环
- Authors
- Name
- noodles
- 每个人的花期不同,不必在乎别人比你提前拥有
简介
事件循环是不同的宿主环境(浏览器或node)对javascript任务进行调度的一种机制,在讨论事件循环的时候首先应该区分node和浏览器(不同宿主环境实现的事件循环机制不同).下面通过介绍一些javascript的基础知识,进而简单的介绍浏览器中的事件循环和node中事件循环.
基本概念
- javascript程序的执行机制是通过栈来管理的.当进入一个函数,就创建了这个函数的执行环境并将这个执行环境推入栈顶,执行完当前的函数后,从栈顶移除对应的执行环境,进入到外层的执行环境.
- javascript的执行是单线程的.但是由于整个事件循环的调度,赋予了javascript对异步任务的强大处理能力.对于异步任务(网络请求,按钮点击)javascript代码调用宿主环境提供的api,将异步任务交给其他的线程去完成.当对应的异步任务完成的时候,将回调函数添加到 回调函数的队列中,由事件循环来实现会回调函数的调用.
marcotasks microtasks
将macrotasks和micortasks单拉出来讲解,是因为理解好这点能更好的理解浏览器或node的任务队列.在实际的实现环境中不同的任务可以放置在不同的任务队列中,然后通过对多个任务队列的调用来完成整个事件循环.
- macrotasks:
- 定时器(timer) setTimeout setInterval setImmediate
- message channel (message channel执行的优先级高于timer)
- I/O
- UI rendering
- microtasks:
- Promises
- MutationObserver(监听DOM)
- 其他api
- queueMicrotask(fn) 将Fn推入微任务执行队列
- requestAnimationFrame
通知浏览器在下次重绘之前调用传入的回调函数,回调函数默认传入函数执行的时间戳.requestAnimationFrame不属于宏任务和微任务,在微任务执行之后执行 - process.nextTick process.nextTick是node上的api,具体的执行时机是在微任务之前执行。
setTimeout(function(){
console.log(1);
});
new Promise(function(resolve){
console.log(2)
for( var i=100000 ; i>0 ; i-- ){
i==1 && resolve()
}
console.log(3)
}).then(function(){
console.log(4)
});
console.log(5);
process.nextTick(() => { console.log('nextTick'); })
输出的顺序依次是 2 3 5 nextTick 4 1
- requestIdleCallback window.requestIdleCallback(callback[, options])
- callback是一个在事件循环空闲时即将被调用的函数的引用,接收一个IdleDeadline参数,通过该参数可以获取当前空闲时间(timeRemaining())以及回调是否在超时时间前已执行的状态(didTimeout)
- options 可选参数 可以配置timeout 表示超时毫秒数未调用回调函数,回调函数将在下一次空闲期间被强制执行。
在具体的实现中只会有一个microTasks队列,简单的理解事件循:
- 浏览器或者node会按照顺序执行自己环境的多个macrotasks队列
- 每执行完一个macrotask队列就会拿出micortasks队列的任务全部执行,然后继续执行下一个macrotask队列

event loop in browser
其实通过对上面相关的知识的介绍,已经可以大致的了解浏览器中事件循环的任务队列 主要有以下几种macrotasks队列
- 事件callback
- I/O(xhr)
- timers
- UI渲染

event loop in node

注意点
- 在浏览器或者node中某些代码的执行会导致event loop失效(停留在处理一个事件队列导致无法进入其他的事件队列的处理).比如浏览器中javascript的长时间执行会导致UI无法交互,node中process.nextTick的递归调用
相关资料
通过microtasks和macrotasks看JavaScript异步任务执行顺序
libuv Design overview How JavaScript works in browser and node? Tasks, microtasks, queues and schedules
Further Adventures of the Event Loop - Erin Zimmer - JSConf EU 2018 菲利普·罗伯茨:到底什么是Event Loop呢? | 欧洲 JSConf 2014
「Nodejs万字进阶」一文吃透异步I/O和事件循环