一文带你彻底搞懂浏览器中的Event Loop

引言

对于从事前端的同学来说,应该对浏览器中的 Event Loop有所了解。这个了解的过程,可能是自己总结,也可能是通过网上的各种讲解。可能,对于前者而言能总结出 Event Loop,说明对它的概念已通透于心。但是,对于后者而言,很可能跌入理解的误区,因为网上有很多种 Event Loop的讲解的版本,各自有描述的重点,并不是能很好地表达 Event Loop的执行流程(我曾经也是这样理解…)。

所以,今天,我们就来详细地认识一下浏览器中的 Event Loop

一、Event Loop 定义


首先,我们来回忆一下,Event Loop的意义何在?众所周知,浏览器的 JS引擎线程为单线程。那么,为了防止代码阻塞的情况出现,所以设置了 Event Loop这种事件循环机制。

往大地讲,它是将一些耗时可能会很长的代码通过异步执行,例如 XMLHTTPRequest请求过程。往小地讲,对于这个异步的过程,通常被称作任务队列消息队列,即 JS引擎在解析 JS代码的时候,会将异步的代码运行结果(通常是回调)放在任务队列中,而任务队列又被分为 marco task(宏任务)和 micro task(微任务)(它们各自由相应的队列维护)。而在每次宏任务执行后(执行一个宏任务),都会询问微任务队列,然后按照 FIFO 先进先出的原则清空微任务队列

常见的宏任务有:

  • 主代码块(即 JS 引擎解析解析同步代码的过程)
  • 页面渲染
  • setTimeout
  • setInterval
  • setImmediate

常见的微任务有:

  • Promise.then
  • MutationObserver

PS:由于只是针对浏览器的 Event Loop,就不提 Node 的 process.nextick 之类的了~

通过,上面的概念性的理解,我想大家可能对 Event Loop如何执行还是有点迷糊,那么接下来,我们就重点通过一个 Demo来深入了解一下 Event Loop的运行机制。

二、Event Loop 运行机制


首先,我们先看一段简单的代码:

console.log(1) // {1}
Promise.resolve().then(() => { // {2}
	console.log(3) 
	Promise.resolve().then(() => { 
		console.log(4)
	})
})
setTimoue(() => { // {3}
	console.log(5) 
	Promise.resolve().then(() => { 
		console.log(6)
	})
})
console.log(2) // {4}

最终会打印输出 1 2 3 4 5 6,这是为什么呢?

1.首先,JS引擎先解析 {1} 时,由于是同步的,所以直接打印出 1

2.然后,解析 {2},由于 Promise.then是微任务(记作任务 A),所以会将它的运行结果放入微任务队列,那么此时任务队列为:
在这里插入图片描述
3.接下来,解析 {3},由于 setTimeout是宏任务(记作任务 B),所以会讲它的运行结果放入宏任务队列,那么此时任务队列为:
在这里插入图片描述
4.然后,再解析 {4},由于是同步的,所以直接打印出 2,此时任务队列不变。

5.此时主代码块执行完了(即宏任务执行完一次),此时去询问微任务队列,清空微任务队列(此时微任务队列刚好只有任务 A),执行完之后的任务队列为:
在这里插入图片描述
并且,此时需要注意的是,在任务 A 的执行过程中,不仅同步打印了 3,而且还生成了一个微任务,即这个微任务也会进入微任务队列,然后出队,即输出 4,这样微任务队列才被清空。

6.清空后微任务队列,会去询问宏任务队列,即执行任务 B(回调),同步打印 5,并且生成一个微任务(记作任务C),讲该微任务的运行结果放到微任务队列中,此时任务队列为:
在这里插入图片描述
7.同样地,在执行完一次宏任务后,会清空微任务队列,即执行任务 C,打印出 6。而自此,微任务队列和宏任务队列都为空,Event Loop就运行结束了。

总结


不知道大家最后弄清楚 Event Loop了没,记忆的过程中有很重要的两点,首先微任务和宏任务是基于队列进行管理的,它遵循 FIFO的原则。并且在每一次宏任务执行一次结束后,都会清空微任务队列。只要,大家明白这两点,然后结合上面的例子理解,我想浏览器中的 Event Loop对你来说应该就是小菜一碟。

发布了140 篇原创文章 · 获赞 16 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_42049445/article/details/104754769