让你理解: 事件循环 eventloop

  • Post author:
  • Post category:其他



微任务和宏任务的讲解, 希望能帮助到你, 戳一戳跳转


(https://blog.csdn.net/weixin_48524561/article/details/124936449)




一、首先说一说什么是宿主环境?

	比如: 寄生虫, 它必须寄生在一个生物的体内; 离开了它就活不下去.

	js代码就是必须寄生在宿主环境里面的, 离开了宿主js代码就运行不了

那么前端常说的宿主环境有哪两种:


  • 浏览器

  • nodejs

当我们在面试的过程当中被面试官问道 “小伙子, 说一说JavaScript的事件循环”. 那么这个面试官的水平可能还不如你.

因为

事件循环并不是针对JavaScript的

, JavaScript中压根就没有事件循环.

只有在

宿主环境中才会有事件循环

的问题. 所以说这个面试官大概率是想问你 “你来说一说宿主环境中的事件循环”.




二、为什么会有事件循环机制?

	JavaScript语言最大的特点就是单线程, 简单的来说就是:"同一时间, 只能做一件事情", 如果有很多事情同时需要执行的话, 就需要排队.

打个比方: 在DOM中同时操作两个线程, 一个线程用来删除某个节点上的元素; 另外一个线程用来在这个线程上添加元素. 你觉得浏览器应该先执行谁了?

所以, 事件循环机制就从此诞生了. 只有等删除操作的线程执行完毕之后, 下一个线程才能执行. 但是如果

一个线程的执行时间太长

的话, 就会

造成拥堵

. 这样

事件循环机制就是为了来解决这个事情

的.




三、拆分里面的原理来说一说事件循环

事件循环 = 事件 + 循环.

  • 事件就是js中的事件类型, 如: 点击事件, 鼠标移入移出事件, 聚焦事件, 失去焦点事件等等.
  • 循环就是一直重复的做, js中的while循环, for循环

这里主要说一说浏览器的事件循环, 以前浏览器给我的感觉就是, 可以运行代码; 面向百度编程, 是不会就搜哪里.

其实浏览器是有很多事情要做的:

  • 执行js代码
  • 请求数据, 接收响应数据
  • 解析css
  • 渲染页面
  • 鼠标的某某某事件等等

但是浏览器是如何去实现的, 其实在浏览器的内部有很多的模块; 每一个模块后面的其实就是一个进程. 也就是说一个模块就是一个进程.




1.1、什么是进程, 什么又是线程?

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

进一步把进程进行划分:


  1. 主进程

    : 用来协调控制其他子进程。

  2. GPU进程

    : 用于3D绘制等。

  3. 渲染进程

    : 就是我们说的浏览器内核,负责具体页面的渲染,脚本执行,事件处理等。浏览器的每个tab页背后就有一个渲染进程。


进程这个单位还是比较大,它进一步拆分多个线程

。可以理解为一个页面上的事还是比较多,要多找些小弟来完成。具体来说,一个渲染进程包括:

4.

主线程

: 统一调度其他线程

5.

GUI渲染线程

: 负责渲染页面,布局和绘制。与JS引擎互斥。

6.

JS引擎线程

: 负责处理解析和执行javascript脚本程序。与GUI渲染线程互斥的

7.

事件触发线程

: 用来控制事件循环(鼠标点击、setTimeout、ajax等)。当事件满足触发条件时,将事件放入到JS引擎所在的执行队列中。(

为什么你触发的事件可以被捕捉到, 是因为此线程在监听

)

8.

setInterval与setTimeout所在的线程

: 定时任务并不是由JS引擎计时的,是由定时触发线程来计时的。计时完毕后,通知事件触发线程。(

其实定时器并不是ECMA所规定的的, 而是宿主环境给予的

)

9.

异步http请求线程

: 浏览器有一个单独的线程用于处理AJAX请求,当请求完成时,若有回调函数,通知事件触发线程。

10.

io线程

: 用来接收其他进程的消息。

每个渲染进程(一个tab页)都有一个主线程,并且主线程非常繁忙,既要处理 DOM,又要计算样式,还要处理布局,同时还需要处理 JavaScript 任务以及各种输入事件(但是如果在JS引擎线程里面写一个死循环的话, 后面的事情都得堵着)。

浏览器又是如何的去有条理的去处理这些

不同的类型的任务在主线程里面执行,

这个时候就

需要一个系统来调度

它们, 指挥它们.

这个调度的系统就是消息队列和事件循环

.




1.2、什么是消息队列, 什么又是事件循环?

任务有很多,人只有一个,且任意时刻只能做一件事(不是一边走路一边听课这种事哈),那怎么办,就是排队呗

	简单的理解就是一个教室只有一个老师, 但是会有很多的学生,
	学生们同时的向老师提出不同的问题, 老师是不可能一下全部的解决掉的,
	而是拿一个小纸条放在讲台上, 学生们把自己的问题写在小纸条上面; 老师解决了当前学生的问题就会优先的解决下一个学生的问题,
	当所有学生的问题全部被解决完毕之后, 老师也就闲下来了; 如果哪个学生还有问题就举手, 老师就再去解决,
	老师就这样一直循环着, 有问题就解决; 没有问题就等待着问题, 再去解决问题.


消息队列就好比是, 同时出现问题; 就得排队. 先来的先做



事件循环就好比是, 同一时间没有问题了, 老师闲下来了; 学生一有问题老师就去解决, 一直循环.


在这里插入图片描述

  1. 主线程上要做很多事情,例如:js代码执行,页面布局计算,渲染等
  2. 主线程同一时刻只能做一件事,事情多了就要排队。所以主线程维护了任务队列。
  3. 某个事件发生时,事件触发线程 就把对应的任务添加到主线程的任务队列中。
  4. 主线程上的任务完成之后,就会从任务队列中取出任务来执行。




四、总结

当面试官问道, 解释一下宿主环境中的事件循环, 可以这样说:

  1. 任务是以事件以及回调1的方式存在的(如: onclick(回调函数))
  2. 当事件(用户的点击, 图片的成功加载)发生时, IO线程就会将其回调添加到任务队列中
  3. 当主线程中的任务完成之后, 就会以从任务队列中取出任务来执行
  4. 此过程不端的重复的去执行, 就会形成一个循环; 此循环称之为eventLoop
  5. 抛开前端, 浏览器不谈, 说一个更广的层面; 在程序世界里面, 事件循环机制是很常见的. 也就是事有很多, 但是干活的只有一个, 那就一定要排队; 并且还有一个机制去指挥它们.



版权声明:本文为weixin_48524561原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。