关于js的事件循环机制剖析

前言

众所周知, JavaScript是单线程这一核心,可是浏览器又能很好的处理异步请求,那么到底是为什么呢?其中的原理与事件循环机制大有关系。

在探索事件循环之前,我们得先了解浏览器执行线程~~

浏览器的渲染进程是多线程的,浏览器每一个tab标签都代表一个独立的进程,其中浏览器内核属于浏览器多进程中的一种,主要负责页面渲染,脚本执行,事件处理等。其包含的线程有以下几种

GUI 渲染线程:负责渲染页面,解析 HTML,CSS 构成 DOM 树;
JS 引擎线程:解释执行代码、用户输入和网络请求;
事件处理线程:click、mouse等交互事件发生后将事件函数放入队列;
定时器触发线程:等时间结束后执行函数推入任务队列中;
http网络请求线程:处理用户的get、post请求,返回结果推入任务队列中。

了解了浏览器渲染流程,还要了解JS的运行机制。JS的运行机制就是事件循环

执行栈

JS运行的环境称之为宿主环境。

执行栈:call stack,一个数据结构,用于存放各种函数的执行环境,每一个函数执行之前,它的相关信息会加入到执行栈。函数调用之前,创建执行环境,然后加入到执行栈;函数调用之后,销毁执行环境。

事件循环

js中所有的任务可以分为同步任务和异步任务,同步任务是立即执行的任务,同步任务一般会直接进入到主线程中执行;而异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout 定时函数等都属于异步任务,异步任务会通过任务队列(先进先出)的机制来进行协调。同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入任务队列。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 这种不断重复就是我们说的 Event Loop (事件循环)。具体流程如下图。

在事件循环中,每进行一次循环操作称为tick,每一次 tick 的任务键的步骤可以总结如下:1.执行一个宏任务(栈中没有就从事件队列中获取);2.执行过程中如果遇到微任务,就将它添加到微任务的任务队列中;3.宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行);4.当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染;5.渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

宏任务主要包含:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
微任务主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)

事件循环例子

console.log('script start');
//整体 script 作为第一个宏任务进入主线程,遇到 console.log,输出 script start
setTimeout(function() {
  console.log('setTimeout');
}, 0);
//遇到 setTimeout,其回调函数被分发到宏任务 Event Queue 中
Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});
//遇到 Promise,其 then函数被分到到微任务 Event Queue 中,记为 then1,之后又遇到了 then 函数,将其分到微任务 Event Queue 中,记为 then2
console.log('script end');
//遇到 console.log,输出 script end

如此,Event Queue(事件队列)中存在三个任务:宏任务:setTimeout 微任务:then1、then2。执行微任务首先then1,输出 promise1, 然后执行 then2,输出 promise2,这样就清空了所有微任务

执行 setTimeout 任务,输出 setTimeout 至此,输出的顺序是:script start, script end, promise1, promise2, setTimeout

总结:

JavaScript 是一门单线程语言,异步操作都是放到事件循环队列里面,等待主执行栈来执行的,并没有专门的异步执行线程。

到此这篇关于js的事件循环机制的文章就介绍到这了,更多相关js事件循环内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 实例分析js事件循环机制

    本文通过实例给大家详细分析了JS中事件循环机制的原理和用法,以下是全部内容: var start = new Date() setTimeout(function () { var end = new Date console.log('Time elapsed:', end - start, 'ms') }, 500) while (new Date() - start < 1000) { } 有其他语言能完成预期的功能吗?Java, 在Java.util.Timer中,对于定时任务的解决方案

  • 理解JS事件循环

    伴随着JavaScript这种web浏览器脚本语言的普及,对它的事件驱动交互模型,以及它与Ruby.Python和Java中常见的请求-响应模型的区别有一个基本了解,对您是有益的.在这篇文章中,我将解释一些JavaScript并发模型的核心概念,包括其事件循环和消息队列,希望能够提升你对一种语言的理解,这种语言你可能已经在使用但也许并不完全理解. 这篇文章是写给谁的? 这篇文章是针对在客户端或服务器端使用或计划使用JavaScript的web开发人员的.如果你已经精通事件循环,那么这篇文章的大部

  • 详解JS浏览器事件循环机制

    先来明白些概念性内容. 进程.线程 进程是系统分配的独立资源,是 CPU 资源分配的基本单位,进程是由一个或者多个线程组成的. 线程是进程的执行流,是CPU调度和分派的基本单位,同个进程之中的多个线程之间是共享该进程的资源的. 浏览器内核 浏览器是多进程的,浏览器每一个 tab 标签都代表一个独立的进程(也不一定,因为多个空白 tab 标签会合并成一个进程),浏览器内核(浏览器渲染进程)属于浏览器多进程中的一种. 浏览器内核有多种线程在工作. GUI 渲染线程: 负责渲染页面,解析 HTML,C

  • 前端js中的事件循环eventloop机制详解

    前言 我们知道 js 是单线程执行的,那么异步的代码 js 是怎么处理的呢?例如下面的代码是如何进行输出的: console.log(1); setTimeout(function() { console.log(2); }, 0); new Promise(function(resolve) { console.log(3); resolve(Date.now()); }).then(function() { console.log(4); }); console.log(5); setTim

  • JS前端知识点总结之页面加载事件,数组操作,DOM节点操作,循环和分支

    本文实例讲述了JS前端知识点总结之页面加载事件,数组操作,DOM节点操作,循环和分支.分享给大家供大家参考,具体如下: 页面加载事件的比较 window.onload jquery 中的 document.ready document.ready = function (callback) { // 兼容FF,Google if (document.addEventListener) { document.addEventListener('DOMContentLoaded', function

  • javascript闭包传参和事件的循环绑定示例探讨

    今天看到一个javascript的题目,按常理循环绑定事件,但是得到的结果却不是想要的. 复制代码 代码如下: <a href="#">text</a> <br> <a href="#">link</a> <script> var as = document.getElementsByTagName('a'); for ( var i = as.length; i--; ) { as[i].on

  • JavaScript运行机制之事件循环(Event Loop)详解

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. JavaScript的单线程,与它的用途有关.作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM.这决定了它只能是单线程,否则会带来很复杂的同步问题.比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线

  • 实例分析JS与Node.js中的事件循环

    这两天跟同事同事讨论遇到的一个问题,js中的event loop,引出了chrome与node中运行具有setTimeout和Promise的程序时候执行结果不一样的问题,从而引出了Nodejs的event loop机制,记录一下,感觉还是蛮有收获的 console.log(1) setTimeout(function() { new Promise(function(resolve, reject) { console.log(2) resolve() }) .then(() => { con

  • 关于js的事件循环机制剖析

    前言 众所周知, JavaScript是单线程这一核心,可是浏览器又能很好的处理异步请求,那么到底是为什么呢?其中的原理与事件循环机制大有关系. 在探索事件循环之前,我们得先了解浏览器执行线程~~ 浏览器的渲染进程是多线程的,浏览器每一个tab标签都代表一个独立的进程,其中浏览器内核属于浏览器多进程中的一种,主要负责页面渲染,脚本执行,事件处理等.其包含的线程有以下几种 GUI 渲染线程:负责渲染页面,解析 HTML,CSS 构成 DOM 树: JS 引擎线程:解释执行代码.用户输入和网络请求:

  • 一篇文章带你了解vue.js的事件循环机制

    目录 一.事件循环机制介绍 二.经典事件循环面试题 总结 一.事件循环机制介绍 JS是单线程的语言,浏览器和Node.js定义了各自的Event Loop(事件循环机制)则是用来解决异步问题.将程序分为“主线程(执行栈)”与“Event Loop线程”,“主线程”自上而下依次执行同步任务,“Event Loop线程”将异步任务推入宏任务队列与微任务队列去执行. 事件循环机制从整体上告诉了我们 JavaScript 代码的执行顺序 Event Loop 即事件循环,是指浏览器或Node 的一种解决

  • 一文详解JS中的事件循环机制

    目录 前言 1.JavaScript是单线程的 2.同步和异步 3.事件循环 前言 我们知道JavaScript 是单线程的编程语言,只能同一时间内做一件事,按顺序来处理事件,但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这又是为什么呢?本文来总结一下js 的事件循环机制. 1.JavaScript是单线程的 JavaScript 是一种单线程的编程语言,只有一个调用栈,决定了它在同一时间只能做一件事.在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行.在

  • 实例详解JS中的事件循环机制

    目录 一.前言 二.宏.微任务 三.Tick 执行顺序 四.案例详解 1.掺杂setTimeout 2.掺杂微任务,此处主要是Promise.then 3.掺杂async/await 一.前言 之前我们把react相关钩子函数大致介绍了一遍,这一系列完结之后我莫名感到空虚,不知道接下来应该更新有关哪方面的文章.最近想了想,打算先回归一遍JS基础,把一些比较重要的基础知识点回顾一下,然后继续撸框架(可能是源码.也可能补全下全家桶).不积跬步无以至千里,万丈高楼咱们先从JS的事件循环机制开始吧,废话

  • node.js事件循环机制及与js区别详解

    目录 一.是什么 二.流程 三.题目 一.是什么 在浏览器事件循环(opens new window)中,我们了解到javascript在浏览器中的事件循环机制,其是根据HTML5定义的规范来实现 而在NodeJS中,事件循环是基于libuv实现,libuv是一个多平台的专注于异步IO的库,如下图最右侧所示: 上图EVENT_QUEUE 给人看起来只有一个队列,但EventLoop存在6个阶段,每个阶段都有对应的一个先进先出的回调队列 二.流程 上节讲到事件循环分成了六个阶段,对应如下: tim

  • 详解JavaScript事件循环机制

    众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. There a

  • JavaScript 关于事件循环机制的刨析

    目录 前言: 一.事件循环和任务队列产生的原因: 二.事件循环机制: 三.任务队列: 3.1 任务队列的类型: 3.2 两者区别: 3.3 更细致的事件循环过程 四.强大的异步专家 process.nextTick() 4.1 process.nextTick()在何时调用? 前言: 这次主要整理一下自己对 Js事件循环机制,同步,异步任务,宏任务,微任务的理解,大概率暂时还有些偏差或者错误.如果有,十分欢迎各位纠正我的错误! 一.事件循环和任务队列产生的原因: 首先,JS是单线程,这样设计也是

  • 简单聊聊JavaScript的事件循环机制

    目录 前言 概念 举个栗子 TIP 再次举个栗子 总结 前言 JavaScript是一门单线程的弱类型语言,但是我们在开发中,经常会遇到一些需要异步或者等待的处理操作. 类似ajax,亦或者ES6中新增的promise操作用于处理一些回调函数等. 概念 在JavaScript代码执行过程中,可以分为同步队列和异步队列. 同步任务类似我们常说的立即执行函数,不需要等待可以直接进行,可以直接进入到主线程中去执行,类似正常的函数调用等. 异步队列则是异步执行函数,类似ajax请求,我们在发起的过程中,

随机推荐