事件循环与进程,线程
作为科班毕业的学生,对于进程与线程应该是必须了解的,但是由于自己大学时期贪玩,所以又重新复习了一下,并且结合事件循环来描述。
什么是事件循环
JavaScript是一门单线程语言。即只有一个线程,代码顺序执行,容易出现代码阻塞。
Event Loop(事件循环)是javaScript和nodejs中一种防止阻塞的机制,同时也是异步的原理。
什么是进程和线程
理论概念:
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程(thread)是操作系统能够进行运算调度的最小单位。一个进程中可以并发多个线程,每条线程并行执行不同的任务。
按照我个人的理解:
程序运行时,需要占据一定的内存空间,这就是进程。不同的程序拥有不同的进程。例如:我们的手机QQ和微信。这是两个互相独立的进程。任意一方的数据都不会影响到对方的内存空间。
进程和下面的这道面试题所要达到的目的其实是一样的
vue中为什么要用这种形式作为数据返回:
面试题中vue组件为什么要通过对象的形式来定义数据:即为了形成独立的作用域,这样在一个父组件中,调用多个不同的子组件,其实调用的是生成的数据副本,组件之间的数据不会互相影响。
data(){
return {
show: true
}
}
浏览器的线程
推荐大家阅读这篇文章浏览器的进程与线程
浏览器主要的进程包括以下:
- 浏览器进程
主要负责界面显示,用户交互,子进程管理。浏览器会启动多个线程处理不同的任务。 - 网络进程
负责网络资源的加载,浏览器启动多个线程来处理不同的网络任务。 - 渲染进程
渲染进程启动后,会开启一个渲染主进程,主进程负责执行我们的html,css,js代码。
渲染主线程执行原理
对于渲染主线程来说,要处理的任务量是巨大的,在这些任务中难免掺杂着一些计时器,网络请求以及一些其他的任务,但是js是单线程语言,如果等待任务执行完成再继续执行,就会导致页面等待,给用户造成卡死的错觉。
因此,事件循环应运而生。
- 渲染主进程会进入无限循环的状态。
- 每一次循环都会检查消息队列中是否有任务进行执行,如果存在任务,取出任务并进行下一次的循环,重复这个过程,直至消息队列为空,进入休眠状态。
- 其他所有的线程都可以随时向消息队列添加任务。新任务按照栈(先进先出)的方式进行添加,即每次添加在末尾,如果主线程是休眠状态,则会唤醒然后继续循环拿取任务。
这便是事件循环,同样是异步的原理。
进一步解析
任务的优先级问题,消息队列中能否插队呢?
最初我学习前端的时候,有微任务和宏任务的概念,微任务是优先于宏任务进行执行的。
常见的微任务:Promise,process.nextTick,MutationBbserver
常见的宏任务:script,定时器,延时器等
微任务的优先级是大于宏任务的。
现在由于浏览器的复杂化,单纯的宏任务和微任务已经不足以处理复杂的场景需求。
根据渡一老师的课程中讲到,当前的chrome中,至少包含了三种队列。
- 延时队列:⽤于存放计时器到达后的回调任务,优先级「中」
- 交互队列:⽤于存放⽤户操作后产⽣的事件处理任务,优先级「⾼」
- 微队列:⽤户存放需要最快执⾏的任务,优先级「最⾼」
在谷歌浏览器的源码中,也同样标明了不同的taskType对应的优先级。
因此,现如今的浏览器执行机制,先处理主线程中的任务,执行完成之后,遍历微队列任务,放入到主线程中进行执行,然后是交互队列,即用户的操作,最后是延时器,定时器等队列。(当页面内容发生改变时,会生成绘制任务,绘制任务同样需要遵循事件循环。)