事件循环(谷歌浏览器称消息循环messageloop)

本篇文章将会结合浏览器(google浏览器为例)源码及W3C标准从根本讲解事件循环的实现方式

结论:由于js是单线程的,所以才会产生事件循环.而事件循环是浏览器用来实现异步的方式,否则浏览器在处理延时或用户交互时由于同步会造成浏览器进程阻塞也就是页面卡死(个人观点).

首先如果要理解事件循环我们需要了解浏览器是怎么运行的(以谷歌浏览器为例,不同浏览器有细微差别):

进程与线程:

        任何的程序运行都需要在内存中开辟一块内存空间.例如流水线的机器需要工作就必须要一块空间放置机器,.我们可以将机器所需要的空间理解为一个进程.

        这条流水线上的每一个工人可以理解为线程.一个进程需要工作就需要每个工人分工明确.

每一个进程都至少需要一个工人来开启机器.开启机器这个人启动机器之后流水线的传送带自动开启.也就是进程开启后会自动创建一个线程,称为主线程(传送带),传送带上可以有多名工人操作,所以一个进程可以包含多个线程

浏览器中的渲染进程:

        浏览器中有许多进程.其中事件循环就发生在渲染进程中.目前谷歌浏览器中一个页面会启动一个渲染进程(每个页面单独渲染).

        那么渲染进程是怎么工作的呢?

浏览器的渲染进程启动后会开启多个进程,而第一个开启的线程(主线程)就处理我们html中的html,css解析和js的执行(其中的细节基础不好的同学可以去看看浏览器的渲染实现)

主线程要做的工作是非常多 且繁琐的,比如主线程在执行一个函数或者任务时,用户和页面有交互或者之前某个时间点设置的settimeout到时间了这个时候浏览器就不知道怎么办了.

这个时候就产生了事件循环(由于js只在这个线程中执行所以才有上面的结论:由于js是单线程的,所以才会产生事件循环),事件循环遵循先进先出的原则------也就是排队.在主线程启动时会一直从消息队列(或者说事件队列)中取出第一个事件,所以先排队的人先处理.在google浏览器的源码中我们可以看见一个for(;;)的死循环,它会不断的从队列中取出下一个事件next_work_info,

在这个过程中本身可能产生新的任务,或者别的进程也可能产生新的任务(例如网络请求产生的渲染任务),所有新加的任务都会从队列最后添加.主线程不断 取出任务丶执行任务丶(添加任务)丶取出任务 这样的过程就叫做事件循环

有了事件循环之后按理说先排队的先拿奶茶不会有问题才对.但是在有时候会出现一些浏览器预料不到的情况.例如定时器.比如:浏览器在处理一个3秒的定时器时按照先进先出原则就得等3秒过后主线程才能往下执行,在这3秒钟内主线程会导致阻塞进而导致浏览器页面卡死.但是主线程还需要处理非常多的事务,所以是一定不能阻塞的.

这个时候,'异步'应运而生,那么异步是怎么实现的呢?

在浏览器遇到延时任务(包括但不限于定时器,网络请求,延时的用户交互任务)时会将整个任务交给其它线程托管,渲染主线程不管它,继续从消息队列中取出任务执行,(以定时器为例)在定时线程到时间后会将这个任务中的js代码封装成一个消息(或任务)添加至消息队列的末尾.所以在这种情况之下主线程永远都不会阻塞,可以保证主线程一直运行.

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值