前端基础知识库-事件循环

简介: 众所周知JavaScript是个单线程的语言,但是为了能更快更好的处理程序,JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型也是JavaScript异于其他语言(c java等)处理并发任务之处。本篇也是我在工作学习中自己对JavaScript事件循环的理解,下面我们一起来了解下JavaScript中事件循环是如何执行的。

前言


众所周知JavaScript是个单线程的语言,但是为了能更快更好的处理程序,JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型也是JavaScript异于其他语言(c java等)处理并发任务之处。本篇也是我在工作学习中自己对JavaScript事件循环的理解,下面我们一起来了解下JavaScript中事件循环是如何执行的。

javascript中事件循环相关概念

在了解事件循环之前我们需要谈谈常见的语言的执行流程。

  • 多线程:什么事多线程呢,最典型的语言是java,学过Java的小伙伴应该很容易理解,java中的Thread就是用来处理多线程的,及我们在java程序中可以同时运行多个线程。
  • 单线程:不同于多线程,单线程工作的语言在同一时间段只能执行一个任务,就如同JavaScript在添加DOM的同时不能去删除DOM。但是如果仅仅如此拿我们在打开页面的同时去请求接口,那是不是要等接口返回之后才能做其他的事情,从实际情况来看肯定不是这样的,由此就可以引入一个异步的概念。
  • 同步:可以看成一种流程执行方式,执行完A在执行B,这个符合我们正常的做事方式。
  • 异步:同步变成我们都很好理解,A执行完执行B,异步与之相反执行A后直接执行B不用等待A执行完,A通过状体来通知调用A者,或者通过回掉函数来处理这个调用

JavaScript这么语言就是单线程异步执行的,而事件循环就是为了处理异步这种执行方式我们需要一种方式来按照调用顺序执行。

在JavaScript中事件循环如何实现

先看图:

网络异常,图片无法展示
|

上图mdn中对事件循环的可视化描述,下图是我自己对执行流程的可视化描述。

网络异常,图片无法展示
|

从上面两张可视化图中我们可以看出整个事件循环是由以下几块组成:调用栈 任务队列  事件触发线程 WebAPi

  • 调用栈:在JavaScript,js的函数调用形成了一个由若干帧组成的栈。
function A(c){
   return 1+c
}
function B(b) {
  let a = 10 + b;
  return A(a);
}
function C(x) {
  let y = 3;
  return B(x * y);
}
console.log(C(7)); // 32
  • 任务(消息)队列:一个 JavaScript 运行时包含了一个待处理消息的消息队列。每一个消息都关联着一个用以处理这个消息的回调函数。
  • 事件触发线程: 浏览器渲染引擎提供的,它会维护一个 任务队列,我们也可以理解为这是一个任务调度器,他决定何时去将任务队列推到执行栈中,具体的实现比较复杂在此不做过多叙述。
  • WEB API:浏览器一些产生异步任务的API。
//promise
let p = new Promise();
p.then()
//process.nextTick
  • 事件循环流程:调用栈中中的任务都执行完后,栈内将被清空,此时主线程的一轮执行完毕,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。

任务队列

  • 同步任务:任务在主线程上同步执行,以队列的形式执行,前一个完成执行第二个。
  • 异步任务:依赖于主线程执行的任务,但是不存在主线程的任务中,执行条件是当任务队列通知主线程执行某条任务时,此任务才能放入主线程中执行。
  • 浏览器任务:在当代浏览器中同步的任务已经不能满足我们日益复杂的需求,因此浏览器在任务处理上引入了微任务的概念。具体执行如下:

1.宏任务在队列中,当调用栈中的函数执行完毕,事件循环系统会将下一个宏任务推入调用栈中执行,并且在执行过程中收集微任务。

2.当某次事件循环的宏任务执行完成之后,立马执行当前任务队列下微任务中的所有任务。微任务执行过程中将再次收集宏任务,并加入宏任务队列,以此循环往复的执行。

  • 常见宏任务:setTimeout, setInterval, setImmediate,DOM解析渲染 ...# 实现代码
  • 常见的微任务:promise process.nextTick

总结


js中事件循环是JavaScript引擎能高速处理页面操作的基石,如果没有这个能力,那我们就按照单线程的方式来执行页面上的操作,其结果无法想象,假设我们在一个网站上操作,你点击个按钮发送异步请求等到几秒之后页面才能再次操作,我想你永远不会想在此进入这个网站,因此我们如果想要真正的了解整个网站在浏览器上的工作流程第一步是去了解浏览器的事件循环机制。


相关文章
|
3月前
|
前端开发 JavaScript API
No100.精选前端面试题,享受每天的挑战和学习(事件循环)
No100.精选前端面试题,享受每天的挑战和学习(事件循环)
|
2月前
|
消息中间件 Web App开发 前端开发
前端秘法进阶篇之事件循环
前端秘法进阶篇之事件循环
|
存储 安全 前端开发
前端知识库-前端安全系列二(同源策略)
在我们日常开发中在与后台联调的时候是不是会经常遇到CORS错误,作为一名前端开发大家应该都知道这个事浏览器同源策略导致的,如何解决这个问题相信大家都有自己团队的方法。如有不了解的可以看下我之前总结过文章跨域解决方案,本文主要来分析下跨域的原因,以及跨域涉及到的API。
|
存储 Web App开发 JavaScript
前端知识库-前端安全系列一(攻防)
最近重新整理了下自己的前端相关知识,在前端安全这个领域由于最近两年做的事内部项目,对此没有太多的实际应用,借此机会重新去了解下,俗话说温故而知新,从故有的知识中总结获取新的知识才是我们进步的基础。
|
前端开发 JavaScript C++
前端知识库Reactjs进阶系列(组件的加载过程)
最近在项目中遇到react的组件多次渲染的问题,最后虽然顺利解决了但也同时发现了自己对于react生命周期的不熟悉,于是便找出react的文档重新去了解下,重新学习之后总结为以下两个主要知识点:react组件的整个渲染流程 react组件更新的注意点。
|
前端开发 JavaScript
前端基础知识库-ES6基础知识
随着前端的发展,JavaScript应用的领域也越来越广泛,其原本的语法的局限性也越来越明显,这便推动了ECMA制定ECMASCRIPT6(以下简称ES6)规范的推广,目前各大浏览器基本都支持了ES6的语法,下面就来了解下ES6的基本语法。
|
存储 前端开发 JavaScript
前端基础知识库JavaScript闭包
在JavaScript中,闭包对于JavaScript的意义无异于指针在c++中的意义。理解闭包是我们掌握JavaScript这门语言的基础能力,而对闭包的掌握程度就可以看出来你对JavaScript这门语言的深入程度,网上关于闭包的文章也不少但多数让人看过之后一头雾水,也许是自己理解能力较差。所以我还下定决心以提问的方式来理解何谓闭包,希望能给与我有相同境遇的博友一点帮助。
|
移动开发 前端开发 JavaScript
前端知识库前端路由-简介
在前端架构中,路由的设计的合理与否决定了这个项目的是否优秀。现在前端的框架angular,vue react都有对应的路由插件,在页面渲染方便基本都不用我们前端工程师考虑,基本上我们安装他们的文档配置好路由都能良好的运行,但是这并不意味我们不需要去掌握路由的实现原理。
|
JSON 前端开发 JavaScript
前端基础知识库-JavaScript对象的深拷贝
在JavaScript数据类型分为基础类型和引用类型,而引用类型又称为对象,可见了解对象是我们真正掌握JavaScript语言的必备技能。本章主要与大家一起去探索JavaScript对象的一些经常被我们忽略的以及难以理解的知识。好了,废话不多说让我们一起进入JavaScript对象的世界吧。
|
缓存 前端开发 JavaScript
前端知识库Reactjs基础系列五mobx初识
在reactjs中,父子组件,同级组件间的状态传递只能通过props传递,如果需要传递的变量过多,就会导致项目混乱难以维护,并且容易产生意想不到的bug。所以我们需要一个能管理全局状态的工具,如redux,mobx这类的就是为了解决这个问题。