js的事件循环

158 阅读4分钟

注:以下内容从'渡一'袁进老师处习得(侵删)

1. 进程和线程

内存中分配一块地方来执行任务,这一块地方就是一个进程

一个进程可以有多个线程来执行任务,但是至少有一个线程(一个公司可以有多个人,但是最少要有一个人)

2. 浏览器

浏览器包括了多个进程,比如:,并且每一个新建的标签页都是一个新的进程

1.  浏览器进程
2.  网络进程
3.  渲染进程

渲染进程中的渲染主线程负责渲染,html css js等,事件循环就发生在这个线程

浏览器 是一个标签页一个进程,所以标签页开多了会占用内存,谷歌将来可能改成一个站点一个进程

3. 事件循环

  1. 是什么事件循环:
           事件循环又叫消息循环,是浏览器渲染主线程的主要工作方式

           在chrome中,它开启一个不会结束的for 循环,每次循环从消息队列中取出第一个任务来执行,其他的线程只需要在合适的时候将任务放到消息队列的末尾排队

           过去吧消息队列分为:宏任务和微任务,但是现在已经不能满足浏览器的环境,现在是一个更加灵活的处理方式:

           根据w3c的说明:每个任务有不同的类型,但是同一类型只能处在一个队列,不同任务可以在不同的队列,不同队列有不同的优先级,在一次事件循环中,浏览器自行决定任务优先级,但是必须要有一个微队列,微队列的优先级永远是最高的,必须优先调度执行

    消息队列优先级:

           微队列(promise,mutationobserve)>交互队列(用户交互)>延时队列(定时器)

       以前是:微队列>宏队列

2. 为什么要采用异步事件的方式:

       js 是一门单线程的语言,因为他运行在浏览器的渲染主线程中,而渲染主线程只有一个,而主线程还承担这其他很多的任务,比如渲染页面,执行js都在里面

       如果所有任务都采用同步的方式,遇到定时器这种必须要等待的任务的话,就会占用渲染主线程很长的时间,极有可能造成主线程堵塞,导致页面无法及时得到渲染,造成卡死现象

       所以采用异步的方式,具体方法是,当某些任务发生时,比如计时器,网络,事件监听等,主线程将任务派发给其他线程去处理,自己立即结束这个任务,然后当其他线程完成任务时候,再将事先传递的回调函数包装成任务放到消息队列的末尾排队,等待主线程调度执行

这种模式,就可以完成主线程永不阻塞,最大程度保持单线程的流畅执行

3. 总结

       单线程是 事件循环产生的原因,事件循环是异步的实现方式

4. 说人话

       渲染主线程先执行同步任务,异步任务进入消息队列排队,等同步任务执行完成后,执行消息队列中微队列中的任务,再执行宏任务(交互队列(用户交互)>延时队列(定时器))然后一直循环下去
       注意:如果在执行一个延时队列的任务后,产生了一个交互队列的任务,此时延时队列还有别的任务,也会先去执行交互队列任务,等到交互队列任务执行完成后再执行剩下的延时队列的任务

希望这篇文章能对你起到帮助