【各大厂常见面试题4】--事件循环
1.浏览器Event Loop
1.1 浏览器Event Loop 定义
浏览器环境下,js单线程机制使得js执行过程中永远只能同时执行一个任务,每次任务的执行主线
程会优先执行同步任务,每次执行完成所有同步任务后对microtask 做检查看是否为空
,如果为空,则判断是否需要进行渲染页面,如果不需要,再进行下次循环,
如microtask队列不为空则先执行完所有的microtask,再执行下一次宏任务。知道执行完成所有的任务队列。
1.2 浏览器Event Loop 执行顺序
执行同步代码
执行完所有同步代码后且执行栈为空,判断是否有微任务需要执行
执行所有微任务且微任务队列为空
是否有必要渲染页面
执行一个宏任务
1.3 宏任务和微任务
宏任务
setTimeout
setImmediate
setIntarval
requestAnimationFrame
I/O
UI rendering
微任务
process.nextTick
Promise.then
Object.observe
MutationObserver
2.node事件循环
2.1 node事件循环定义
Node.js 在主线程里维护了一个事件队列,当接到请求后,就将该请求作为一个事件放入这个队列中,然后继续
接收其他请求。当主线程空闲时(没有请求接入时),就开始循环事件队列,检查队列中是否有要处理的事件,这时
要分两种情况:如果是非 I/O 任务,就亲自处理,并通过回调函数返回到上层调用;如果是 I/O 任务,就从线
程池中拿出一个线程来处理这个事件,并指定回调函数,然后继续循环队列中的其他事件。当线程中的 I/O 任务
完成以后,就执行指定的回调函数,并把这个完成的事件放到事件队列的尾部等待事件循环,当主线程再次循环
到该事件时,就直接处理并返回给上层调用。
2.2 Node.js事件循环四层
Node.js事件循环四层被分为了四层,分别是 应用层、V8引擎层、Node API层 和 LIBUV层。
应用层: 即 JavaScript 交互层,常见的就是 Node.js 的模块,比如 http,fs
V8引擎层: 即利用 V8 引擎来解析JavaScript 语法,进而和下层 API 交互
NodeAPI层: 为上层模块提供系统调用,一般是由 C 语言来实现,和操作系统进行交互 。
LIBUV层: 是跨平台的底层封装,实现了 事件循环、文件操作等,是 Node.js 实现异步的核心 。
总结:无论是 Linux 平台还是 Windows 平台,Node.js 内部都是通过 线程池 来完成异步 I/O 操作的,而
LIBUV 针对不同平台的差异性实现了统一调用。因此,Node.js 的单线程仅仅是指
JavaScript 运行在单线程中,而并非 Node.js 是单线程。
2.3 node的Event Loop 执行顺序
timers:执行setTimeout() 和 setInterval()中到期的callback。
I/O callbacks:上一轮循环中有少数的I/Ocallback会被延迟到这一轮的这一阶段执行
idle, prepare:队列的移动,仅内部使用
poll:最为重要的阶段,执行I/O callback,在适当的条件下会阻塞在这个阶段
check:执行setImmediate的callback
close callbacks:执行close事件的callback,例如socket.on("close",func)
3. 浏览器事件循环示例
console.log(1);
setTimeout(function() {
console.log(2);
})
var promise = new Promise(function(resolve, reject) {
console.log(3);
resolve();
})
promise.then(function() {
console.log(4);
})
console.log(5);
4.延伸面试题
4.1 题目描述:
如有以下代码,如何改造让其按顺序输出1 2 ?
var promise = new Promise(function(resolve, reject) {
console.log(0);
resolve();
console.log("*****");
})
promise.then(function() {
}).catch(function() {
console.log(1);
}).then(function() {
}).catch(function() {
console.log(2);
})
4.2 思路分析:
利用Promise.reject(reason)方法也会返回一个新的 Promise 实例,
该实例的状态为rejected。catch方法默认会捕获并将报错信息进行输出。
4.3 AC 代码:
var promise = new Promise(function(resolve, reject) {
console.log(0);
resolve();
console.log("*****");
})
promise.then(function() {
reject('失败了')
}).catch(function() {
console.log(1);
}).then(function() {
reject('失败了')
}).catch(function() {
console.log(2);
})
// 输出: 0 ***** 1 2
最后 附其他面试题
【各大厂常见面试题3】--http和https系列
【各大厂常见面试题2】--函数
【各大厂常见面试题1】--变量
读后有收获可以微信请作者喝咖啡,有疑问请加微信讨论