js的事件处理程序底层原理(关于js的事件循环机制剖析)
js的事件处理程序底层原理
关于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事件循环内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
- axios 请求前校验参数(js实现axios限制请求队列)
- js特效星空(ThingJS粒子特效一键实现雨雪效果)
- php生成json信息(php使用json-schema模块实现json校验示例)
- 微信js开发教程(微信JSSDK分享功能图文实例详解)
- JS中Location
- js日期格式化
- js return false的作用
- extjs XTemplate的实例
- vscode react jsx语法 开发环境(React-vscode使用jsx语法的问题及解决方法)
- js 全局变量与局部变量
- mysql 查询json(MySQL处理JSON常见函数的使用)
- php 结果集转json(PHP的JSON封装、转变及输出操作示例)
- JS中错误处理
- python获取json结果保存文本(Python JSON格式数据的提取和保存的实现)
- lombok 代码行数(Lombok实现方式JSR-269)
- php多维数组怎么转换json(php实现的数组转xml案例分析)
- 太鸡贼了,这老小区轻松搞定了停车问题(这老小区轻松搞定了停车问题)
- 太鸡贼了,这老小区轻松搞定了停车问题(这老小区轻松搞定了停车问题)
- 节日我在岗|警景相融 平安相伴(节日我在岗警景相融)
- 战 疫 时刻 致敬每一位石化大学的 守护者(战疫时刻)
- 老弄堂里的市井味道(老弄堂里的市井味道)
- 小米音乐可绑定QQ音乐, QQ音乐 真的会消失在小米的设备上吗(小米音乐可绑定QQ音乐)
热门推荐
- js RegExp用法
- thinkphp快速入门手册(从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解)
- javascript函数工具有哪些(如何让你的JavaScript函数更加优雅详解)
- 如何将类库、DLL发布到Nuget
- css边框和边界教程(css 中多种边框的实现小窍门)
- bootstrap 左右布局(详解Bootstrap网格垂直和水平对齐方式)
- php密钥怎么加密(php校验公钥是否可用的实例方法)
- apache虚拟域名配置(Apache虚拟主机的配置和泛域名解析实现代码)
- angular定义一个管道(Angular管道PIPE的介绍与使用方法)
- thinkphp微信开发实例(ThinkPHP框架下微信支付功能总结踩坑笔记)