「EventLoop」图文并茂-带你完全搞懂事件循环♻️

简介: 「EventLoop」图文并茂-带你完全搞懂事件循环♻️

image.png

大家好,我是速冻鱼🐟,一条水系前端💦,喜欢花里胡哨💐,持续沙雕🌲,是隔壁寒草🌿的好兄弟,刚开始写文章。 如果喜欢我的文章,可以关注➕点赞,为我注入能量,与我一同成长吧~


温馨提示☀️:文章中有大量GIF图片,有可能会加载比较慢,小伙伴们耐心等待一下(我尽力压缩了呜呜)


阅读本文🦀



1.您将了解到事件循环到底是什么

2.为什么javascript是单线程,却可以执行异步函数

3.为什么浏览器要采用事件循环

4.您将了解到什么是javaScript运行时

5.您将了解到事件循环和浏览器重绘之间的联系


image.png

前言🌵


JavaScript 程序员喜欢使用诸如“事件循环”、“非阻塞”、“回调”、“异步”、“单线程”和“并发”之类的词。好像这一切都很明显,但是要找到 JavaScript 实际工作原理的良好解释并不是那么容易,所以让我们学习吧!🕶

前置知识👋


什么是javaScript


JavaScript 是一种解释型语言,而不是一种编译型语言。像 C++ 或 Java 这样的程序在运行之前需要进行编译。源代码通过称为编译器的程序传递,编译器将其转换为机器理解并可以执行的字节码。相比之下,JavaScript 没有编译步骤。相反,浏览器中的解释器会读取 JavaScript 代码,解释每一行,然后运行它。更现代的浏览器使用一种称为即时 (JIT) 编译的技术,该技术将 JavaScript 编译为即将运行的可执行字节码。

  • 单线程 (相当于一个车间只有一个工人)
  • 单并发 (同一时间只能干一件事)
  • 有一个调用堆栈 (javaScript执行上下文)
  • 一个事件循环 (从回调队列中获取回调函数,并将它们放入调用堆栈中,以便执行它们。)
  • 一个回调队列(是一个数据结构,包含所有准备执行的回调函数。)
  • 一些其他API


什么是javaScirpt运行时



javaScript是运行在V8引擎中的,V8 Google 的开源高性能 JavaScriptWebAssembly 引擎,用 C++ 编写。

  • heap(堆内存)主要存放我们的对象
  • stack (栈内存)是我们javaScript的执行上下文环境(execution contexts),还有一些基本数据类型


image.png

什么是WebAPI


浏览器提供的一些额外的东西,比如DOM、AJAX、TIMEOUT等等

Web API 是提供给引擎的功能,但不是 JavaScript 语言本身的一部分。


什么是事件循环


事件循环是一种编程构造或设计模式,用于在程序中等待和分派事件消息。事件循环的工作原理是向某个内部或外部“事件提供者”发出请求(通常在事件到达之前阻止请求),然后调用相关的事件处理程序(“调度事件”)。事件循环有时也称为消息调度程序消息循环消息泵运行循环


正文 🦁



将我们上面提到的这些东西组合起来就是我们今天要了解的事件循环EventLoop

javaScript执行机制


各位小伙伴先看个图,有个大致印象,知道我要说什么,后边都会一一讲解的。

7fe6a4b3489141b28d315feee551ed23.png

JavaScript是一种单线程编程语言,单线程运行时,它具有单个调用堆栈。

它一次只能做一件事,这就是单线程的意思,程序一次可以运行一段代码。还是直接看图吧。

d2b571722f014009a29e74ca96cec7dd.gif

image.png

入一个函数,我们把这个函数放到堆栈中,如果我们从一个函数返回,我们从堆栈的顶部弹出它。


这就是我们的程序出错的时候,你为什么会在控制台看到诸如此类的提示一样

image.png

相信大家也有遇到过堆栈内存溢出的情况吧,这种嵌套死循环,就会不停的在我们的堆栈开辟内存空间最后溢出,导致报错

image.png

当我们的同步代码执行速度很慢的时候


下面我们模拟我们的网络请求是同步的


如何我们的所有代码都是同步执行的,那么就会阻塞我们的线程,当我们的线程被阻塞的时候我们什么也做不了,只有慢慢等待,显然发起网络请求这种操作如果是同步的,那将会带来很严重的后果。但是javaScript又是单线程的,怎么解决呢?

228aabac3dbb4f5391fa82b09c4b1484.gif

当然是将这种耗时的操作异步执行了呀(比如AJAXTimeOut等等),这时候你可能会说了,上次才说了javaScript是单线程的,又怎么执行异步函数呢?

这一点浏览器早就想到了,AJAX、TimeOut等等这些WebAPIs都是浏览提供给javaScript引擎的,它并不属于javaScript语言的一部分。

当我们执行异步函数的时候我们就会把它交给浏览器来管理,就有了我们下面这张图

0f6ea925575340548cbc8d205affa162.gif

WebAPIs:


就是浏览器提供给我们一些执行异步函数的API,它是由浏览器来管理的,和我们的javaScript执行调用栈是隔离开的。


Callbak Queue:


是我们的异步函数回掉队列,当我们异步函数可以执行的时候,浏览器就会将它的回掉函数推送到我们的Callback Queue中


EventLoop :


当我们的javaScript执行栈中没有要执行的语句时,EventLoop就会从我们的队列中依次取出队头的回调函数,将它推送到我们的Stack中,等待Stack执行完毕,继续取队头的回调函数,如此往复。


示例 🐳


示例1 设置一个定时器 ⌚️

3b2bae17b69349228a0227442583f1fe.gif

  • 首先控制台打印 Hi


  • 执行到第二句setTimeout,这时候交给我们的浏览器来处理,浏览器会为你开启一个定时器,它不在javaScript运行时中。


  • 执行第三句,打印  JSConfEu


  • 五秒过后,浏览器将我们的setTimeout回调函数推到 CallBack Queue(task queue)队列中,当stack执行栈中没有需要执行的语句后,evnet Loop就会从我们的 CallBack Queue中取出回调函数执行栈中去执行。


  • 最后打印出 there


Hi=>JSConfEui=>there


即使你将SetTimeout设置为0,它也是会按照上面的步骤依次执行


示例2 发送一个异步网络请求 🍪

aa7b97ae093b47199f6fddbcde771d72.gif

  • 首先打印 Hi
  • 然后发送异步网络请求,交给浏览器来处理。
  • 执行第三句,打印 JSConfEU
  • 当请求完成后,浏览器将它推入task queue任务队列中(也可以叫callback queue)
  • 当stack没有要执行的语句时,eventloop从task queue中取出网络请求的回调函数推入stack中执行
  • 最后打印出网络请求的结果


事件循环和浏览器重绘的关联 🌽


  • 我们需要知道很关键的一点是如果我们的堆栈上有代码还未执行完,我们的浏览器就无法进行渲染,要渲染必须等到堆栈清除为止
  • 渲染的优先级别高于回调函数的优先级别


下图gif不是很清楚,我把代码贴在这里


image.png

1ce65b2ffe074163b059a9cdf7e47004.gif

当我们执行栈中的函数执行完成以后,我们就会先进行一次重绘,然后再去回调队列中去取出回调函数到堆栈中执行,如此往复


参考 📚


收获 🍁


在这篇文章中我们了解到了什么是事件循环,以及JavaScript的运行机制,什么是V8,什么是WebAPI等等,学习底层的原理能让我开拓视野,能够从根源去了解javaScript本质,能快速定位问题,也希望您能在这篇文章中有所收获,希望这篇文章对你有所帮助


结束语 🌞


image.png


那么我的第N篇文章就结束了,文章的目的其实很简单,就是对日常工作的总结和输出,输出一些觉得对大家有用的东西,菜不菜不重要,但是热爱🔥,希望大家能够喜欢我的文章,我真的很用心在写,也希望通过文章认识更多志同道合的朋友,如果你也喜欢折腾,欢迎加我好友,一起沙雕,一起进步

相关文章
|
4月前
|
安全 API
muduo源码剖析之EventLoop事件循环类
EventLoop.cc就相当于一个reactor,多线程之间的函数调用(用eventfd唤醒),epoll处理,超时队列处理,对channel的处理。运行loop的进程被称为IO线程,EventLoop提供了一些API确保相应函数在IO线程中调用,确保没有用互斥量保护的变量只能在IO线程中使用,也封装了超时队列的基本操作。
41 0
|
4月前
|
网络协议 NoSQL API
协程知识点总结
协程知识点总结
|
监控 JavaScript 前端开发
|
前端开发
前端知识案例-eventloop
前端知识案例-eventloop
31 0
前端知识案例-eventloop
线程池详解(通俗易懂超级好)
这个参数的设计完全参考系统运行环境和硬件压力设定,没有固定的参考值,用户可以根据经验和系统产生任务的时间间隔合理设置一个值即可;
线程池详解(通俗易懂超级好)
|
前端开发 JavaScript
每日一题:说说你对事件循环的理解
每日一题:说说你对事件循环的理解
131 0
每日一题:说说你对事件循环的理解
|
监控 C语言 iOS开发
小码哥底层原理之RunLoop
RunLoop是一个运行循环,保证App能够持续运行,处理各种事件,节省CPU资源,没事处理的时候就进入休眠。
128 0
小码哥底层原理之RunLoop
|
监控 Linux C语言
彻底搞懂 select/poll/epoll,就这篇了
之前已经把网络 I/O 相关要点都盘了,还剩 select/poll/epoll 这几个区别没说,这篇就来搞搞它们,并且是从完全理解原理的角度来区分它们。 本来是要上源码的,但是感觉没啥必要,身为应用开发者我觉得理解原理就行了,源码反正看了就忘了,理解才是最重要!所以我就尽量避免代码且用大白话来盘一盘这三个玩意。 话不多说,发车。
280 0
彻底搞懂 select/poll/epoll,就这篇了
|
存储 调度 iOS开发
runloop的基本概念和实现原理
runloop的基本概念和实现原理
326 0
runloop的基本概念和实现原理
|
Java 开发者
手撕源码!线程池核心组件源码剖析
看源码之前,先了解一下该组件 最主要的几个 接口、抽象类和实现类的结构关系。
136 0
手撕源码!线程池核心组件源码剖析