JavaScript疑难杂症系列-事件循环
javascript单线程
浏览器端,复杂的UI环境会限制多线程语言的开发。
例如,一个线程在操作一个DOM元素时,另一个线程需要去删除DOM元素,
这个之间就需要进行状态的同步,何况前端可能不止操作这么一个DOM元素。
所以,为了避免在开发过程中,去进行复杂的同步,选用单线程语言进行开发是最好的解决方案
栈
栈就是和列表类似的一种数据结构,它可以用来解决计算机世界里很多的问题。栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样的操作很快,而且容易实现。
栈的使用遍布程序语言的方方面面,从表达式求值到处理函数调用; 函数调用形成了一个栈帧
具有一种后入先出(LIFO,last-in-first-out)的数据结构
由于栈具有后入先出的特点,所有任何不在栈顶的元素都无法访问,为了拿到栈底的元素,必选先拿掉上面的元素
可在线演示这段代码的执行流程
function fun1(){return 'hello hip-hop';}function fun2(){return fun1();}function fun3(){console.log(fun2());}fun3(); //'hello hip-hop'复制代码
堆(引用类型)
当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本开销较大),这个运行时数据区就是堆内存。
堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,
系统的垃圾回收机制才会在核实的时候回收它对象被分配在一个堆中,即用以表示一个大部分非结构化的内存区域
队列
排队在第一个的人先办理业务,其它人只能排着,直到轮到他们为止只能在末尾插入元素,在队首删除元素。
队列用于存储按顺序排列的数据先进先出列被用在很多地方。比如提交操作系统执行一系列进程。打印任务池等。一些仿真系统用来模拟银行或杂货店里排队的顾客
事件循环机制
这幅图片中,我们可以看到完整的执行流程,其中涉及到的异步事件有DOM事件、ajax请求和setTimeout。所以,整体的执行流程是这样子的:
- 所有同步任务会在主线程的调用栈中执行。
- 在主线程之外,还有一个任务队列,一旦指定事件发生之后,异步任务就会被放入任务队列中
- 当主线程执行完调用栈中的同步任务时,会遍历任务队列,将任务队列中的任务放入主线程中执行。而之后事件循环一直会去遍历任务队列,一旦有任务放入就会放入主线程中执行。
这样,我们就已经初步了解了同步和异步之间的实现,以及浏览器中的事件循环机制。
任务队列
所谓任务是WebAPIs返回的一个个通知,让JS主线程在读取任务队列的时候得知这个异步任务已经完成,下一步该执行这个任务的回调函数了。
主线程拥有多个任务队列,不同的任务队列用来排列来自不同任务源的任务。
任务源是什么?像setTimeout/Promise/DOM事件等都是任务源,来自同类任务源的任务我们称它们是同源的,比如setTimeout与setInterval就是同源的。
在ES6标准中任务队列又分为宏观任务队列和微观任务队列
宏观与微观任务队列
ES6标准中任务队列存在两种类型,一种就是上边提到的一些队列,
宏观任务队列(macrotask queue):setTimeout、网络请求Ajax、用户IO等,
微观任务队列(microtask queue),Promise就属于微观任务队列
在执行栈执行的过程中会把属于微观任务队列的任务分配到相应的微观任务队列中去。而在调用栈执行空之后,主线程读取任务队列时,会先读取所有微观任务队列,然后读取一个宏观任务队列,再读取所有的微观任务队列
复制代码
setTimeout(function(){console.log(4)},0);
new Promise(function(resolve){console.log(1)for( var i=0 ; i<10000 ; i++ ){i==9999 && resolve()}console.log(2)
}).then(function(){console.log(5)
});
console.log(3);复制代码
- 脚本开始执行,最先遇到setTimeout,交给浏览器去计时,达到setTimeout限制最短计时之后,把这个任务推入setTimeout队列。
- 遇到Promise构造函数,构造函数参数执行,输出1,调用resolve改变Promise对象的状态,然后输出2。
Promise对象调用then方法,将这个任务推入Promise任务队列。
执行console.log(3),输出3。 - 调用栈为空,读取任务队列,按照 读取所有微观任务队列 -> 执行 ->
- 读取一个宏观任务队列 -> 执行 ->
- 读取所有微观任务队列 -> 执行 ->
- 再读取一个宏观任务队列…的顺序。
- 读取所有微观任务队列中的任务,执行这些任务指定的回调函数。执行then指定的回调函数,输出5(微观任务队列也具有优先级)。
- 最后读取到setTimeout的任务,执行回调函数,输出4。
所以最后的输出顺序是1,2,3,5,4,而不是1,2,3,4,5。如果不清楚微观任务队列的执行机制,很容易将两个异步任务归为一类,将执行顺序判断错误
零延迟
零延迟并不是意味着回调会立即执行。 在零延迟调用 setTimeout 时,其并不是过了给定的时间间隔后就马上执行回调函数。
其等待的时间基于队列里正在等待的消息数量。 在下面的例子中,"this is just a message" 将会在回调
(callback) 获得处理之前输出到控制台, 这是因为延迟是要求运行时 (runtime) 处理请求所需的最小时间,但不是有所保证的时间
(function () {console.log('this is the start');setTimeout(function cb() {console.log('this is a msg from call back');});console.log('this is just a message');setTimeout(function cb1() {console.log('this is a msg from call back1');}, 0);console.log('this is the end');})();// "this is the start"
// "this is just a message"
// "this is the end"
// "this is a msg from call back"
// "this is a msg from call back1"复制代码
JavaScript疑难杂症系列-事件循环相关推荐
- php event loop,理解javascript中的事件循环(Event Loop)
背景 在研究js的异步的实现方式的时候,发现了JavaScript 中的 macrotask 和 microtask 的概念.在查阅了一番资料之后,对其中的执行机制有所了解,下面整理出来,希望可以帮助 ...
- JavaScript中的事件循环
JavaScript是单线程单并发语言 单线程:主程序只有一个线程,即同一时间片段内其只能执行单个任务. 引发的问题: 单线程,意味着任务都需要排队,前一个任务结束,才会执行后一个任务.若前一个任务耗 ...
- html5多线程例子,javascript的单线程事件循环及多线程介绍
前言 其实我前面文章对于改变js的执行顺序及多线程都有相关介绍!例如,我们可以用setTimeout(fn,0)改变代码执行循序,文章最后也提及了Event Loop(事件循环).同时,js的Work ...
- JavaScript event loop事件循环 macrotask与microtask
macrotask 姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...
- 同一个按钮绑定多个事件_带你走进JavaScript世界系列——事件处理程序之 IE 事件处理...
IE 事件处理程序 IE 实现了与 DOM 中类似的两个方法:attachEvent() 和 detachEvent() .这两个方法接收相同的两个参数:事件处理程序名称和事件处理程序函数.通过 at ...
- 如何跟面试官解释事件循环
关于事件循环的问题面试官都尤其的偏爱,所以说准备面试如果不搞懂事件循环是非常危险的. 当面试官问你了解浏览器事件循环吗?这只是一个开始,接下来: 为什么js在浏览器中有事件循环机制 事件循环有哪些任务 ...
- 对事件循环的一点理解
最近工作需要学习了解webworker-threads以应对Javascript多线程处理CPU密集型的可能性:参考文档JavaScript多线程之二 Node.js中的Web Worker; 以下是 ...
- javascript系统系列:浅析js中的浏览器循环事件(eventLoop)
大家好,我是前端岚枫,今天主要跟大家分享我整理的浏览器事件循环eventLoop相关:eventloop, 微任务.宏任务等,此方面内容在我们的工作中常用到, 也是大厂面试经常提问的问题,希望下面文章 ...
- 技术干货 | JavaScript 之事件循环(Event Loop)
导读:学过 JavaScript(下文简称 JS) 的都知道它是一门单线程的.非阻塞的脚本语言.单线程意味着,JS 代码在执行的任何时候,都只有一个主线程来处理所有的任务,这也就意味着 JS 无法进行 ...
最新文章
- mysql数据库管理系统的配置文件是_MySQL学习笔记_1_MySQL数据库管理系统概述
- 中国文学发展史思维导图
- ELK学习笔记之ElasticSearch简介
- Android中怎样在项目中引入别的项目中正使用的library
- php mysql插入的数据有引号_php – 由于’引号’的不同,数据没有插入到mysql数据库中...
- 写一个Android输入法01——最简步骤
- 电大计算机网络技术基础,电大--2016年电大 计算机与网络技术基础小抄已排版.doc...
- Spring Boot,Sprint Batch 学习
- Mybatis 图解
- Win10 系统 WebLogic 12cR2 下载与安装图解
- 近期CDRX4正常使用中突然提示盗版弹窗您的产品已被禁用永久解决教程
- FICO 财务替代创建
- 2022款联想拯救者R7000P和联想小新Pro16 选哪个好
- 人群计数数据集汇总和详细介绍,全网最全,crowd counting datasets
- 一键复制粘贴工具使用教程
- 大神嵌入式linux系统的路径规划与经验分享(干货满满)
- 辩证唯物论和唯物辩证法区别
- 山东大学项目实训-地图圈系统-APP(2)
- html做的网页连wifi,ESP32通过WEB页面连接WIFI
- 商标“李鬼”防不胜防,事关宁德时代
热门文章
- 远程服务器返回错误: (500) 内部服务器错误。_[源码和文档分享]基于TCP SOCKET实现的远程聊天系统...
- 如何格式化电脑_U盘提示格式化后如何恢复数据
- 迁移学习中的负迁移:综述
- JAVA实现判断树的子结构及树的镜像问题(《剑指offer》)
- 字节博士搞的AI火了,一键完美分离人声和伴奏 | 在线可玩
- 包浆网图分分钟变高清,伪影去除、细节恢复更胜前辈AI,下载可玩|腾讯ARC实验室出品...
- 图形学大牛归国投身产业,还是个让女孩们败家的赛道
- GitHub遭炮轰:Copilot“抄袭”已经失控,为训练AI侵权整个社区
- 「思想钢印」成真!33位中美科学家最新成果:用光成功改变大脑认知
- 为了杀蚊子,这位博士用树莓派DIY了一把激光枪,网友:伤到人怎么办?