Event Loop 也叫做“事件循环”,它其实与 JavaScript 的运行机制有关。

JS初始设计

JavaScript 在设计之初便是单线程,程序运行时,只有一个线程存在,在特定的时候只能有特定的代码被执行。这和 JavaScript 的用途有关,它是一门浏览器脚本语言,通常是用来操作 DOM 的,如果是多线程,一个线程进行了删除 DOM 操作,另一个添加 DOM,此时该如何处理?所以 JavaScript 在设计之初便是单线程的。

虽然 HTML5 增加了 Web Work 可用来另开一个线程,但是该线程仍受主线程的控制,所以 JavaScript 的本质依然是单线程

线程和进程

进程和线程是操作系统中的概念,在操作系统中,一个任务就是一个进程,比如你在电脑上打开了一个浏览器来观看视频,便是打开了一个浏览器进程,此时又想记录视频中的重要信息,于是你打开了备忘录,这便是一个备忘录进程,系统会为每个进程分配它所需要的地址空间,数据,代码等系统资源。如果把一个进程看做一个小的车间,车间里有很多工人,有的负责操作机器,有的负责搬运材料,每个工人可以看做一个线程,线程可以共享进程的资源。可以说,线程是进程的最小单位,一个进程可以包含多个线程。

执行栈和任务队列

单线程的 JavaScript 一段一段地执行,前面的执行完了,再执行后面的,试想一个,如果前一个任务需要执行很久,比如接口请求、I/O 操作,此时后面的任务只能干巴巴地等待么?干等不仅浪费了资源,而且页面的交互程度也很差。JavaScript 意识到了这个问题,他们将任务分成了同步任务和异步任务,对于二者有不同的处理。

JavaScript 在运行时会将变量存放在堆(heap)和栈(stack)中,堆中通常存放着一些对象,而变量及对象的指针则存放在栈中。JavaScript 在执行时,同步任务会排好队,在主线程上按照顺序执行,前面的执行完了再执行后面的,排队的地方叫执行栈(execution context stack)。JavaScript 对异步任务不会停下来等待,而是将其挂起,继续执行执行栈中的同步任务,当异步任务有返回结果时,异步任务会加入与执行栈不一样的队列,即任务队列(task queue),所以任务队列中存放的是异步任务执行完成后的结果,通常是回调函数。

当执行栈的同步任务已经执行完成,此时主线程闲下来,它便会去查看任务队列是否有任务,如果有,主线程会将最先进入任务队列的任务加入到执行栈中执行,执行栈中的任务执行完了之后,主线程便又去任务队列中查看是否有任务可执行。主线程去任务队列读取任务到执行栈中去执行,这个过程是循环往复的,这便是 Event Loop,事件循环。

网上有张流传甚广的图对这一过程进行了总结,在图中我们可以看到,JavaScript 在运行时产生了堆和栈,ajax、setTimeout 等异步任务被挂起,异步任务的返回结果加入任务队列,主线程会循环往复地读取任务队列中的任务,加入执行栈中执行。

 

(JavaScript 运行机制,图片来源于网络)

宏任务与微任务

异步任务有更深一层的划分,它们是宏任务(macro task)和微任务(micro task),二者的执行顺序也有差别。在上面我们讲到异步任务的结果会进入任务队列中,对于不同的事件类型,宏任务会加入宏任务队列,微任务会加入微任务队列。在执行栈中的同步任务执行完成后,主线程会先查看任务队列中的微任务,如果有没有,则去宏任务队列中取出最前面的一个事件加入执行栈中执行;如果有,则将所有在微任务队列中的事件依次加入执行栈中执行,直到所有事件执行完成后,再去宏任务中取出最前面的一个事件加入执行栈,如此循环往复。

由此我们可以得出结论,主线程总是会先查看微任务队列,等到微任务队列中的事件都处理完成后,再去宏任务队列中添加一个事件到任务栈中执行。

常见的宏任务有 setTimeout,setInterval;常见的微任务有 new Promise。

代码例子体验

console.log(1)setTimeout(function() {console.log(2)new Promise(function(resolve) {console.log(3)resolve(4)}).then(function(num) {console.log(num)})
}, 300)new Promise(function(resolve) {console.log(5)resolve(6)
}).then(function(num) {console.log(num)
})setTimeout(function() {console.log(7)
}, 400)

我们一步步来分析上面的执行顺序,当程序开始执行时,首先打印出 1,然后遇到了 setTimeout,主程序将它挂起,300 毫秒后它的回调函数进入宏任务队列,我们记做 setTimeout1。随后遇到了 new Promise,resolve 部分是同步执行的,所以会打印出 5,then 中的回调函数进入微任务队列,我们暂时记做 promise1。最后是 setTimeout,同理在 400 毫秒后加入了宏任务队列,我们记做 setTimeout2。

此时任务队列的情况如下:

宏任务

微任务

setTimeout1

promise1

setTimeout2

 

执行栈中的同步任务执行完成后,主线程查看任务队列时发现存在微任务,于是把 promise1 执行了,打印出 6。此时微任务队列已经空了,于是开始查看宏任务队列,将 setTimeout1 的回调函数加入任务栈开始执行,于是首先打印出 2,之后是 3,再将 then 中的回调函数加入微任务队列,我们记做 promise2。

此时任务队列的情况如下:

宏任务

微任务

setTimeout2

promise2

此时执行栈也空了,于是将微任务 promise2 加入执行栈,打印出 4。此时微任务已经执行完,再查看宏任务队列,于是执行 setTimeout2,打印出 7。

所以代码中的输出顺序是 1,5,6,2,3,4,7。

注意,主线程对微任务的读取是逐个读取,直到微任务队列为空,再读取宏队列,对宏任务队列的读取在一个循环中只读取一个。

小结

我们了解了 JavaScript 的运行机制,它是单线程的。JavaScript 中的任务可分为同步任务和异步任务,同步任务总是先进入执行栈中执行,异步任务会被挂起,直到有结果返回时,异步任务会进入任务队列中等待主线程读取执行。当执行栈为空时,主线程便会循环往复地读取任务队列中的事件,进入执行栈执行,这个过程叫 Event Loop。主线程对任务队列的读取也有先后之分,首先会去查找微任务,微任务队列的事件都执行完毕后,再读取最前面的宏任务进行执行,执行完再读取微任务队列,这个过程也是循环往复的。

 

转载于:https://www.cnblogs.com/Joe-and-Joan/p/10687551.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/449259.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/449259.shtml
英文地址,请注明出处:http://en.pswp.cn/news/449259.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot -Shiro配置多Realm

2019独角兽企业重金招聘Python工程师标准>>> 核心类简介 xxxToken:用户凭证 xxxFilter:生产token,设置登录成功,登录失败处理方法,判断是否登录连接等 xxxRealm:依据配置的支持Token来认证用户信…

idea工具debug断点红色变成灰色

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 没事别瞎点,禁用了断点当然不走了 转自:https://blog.csdn.net/anlve512/article/details/54583469

2020-3-20前端题目

题目一&#xff1a; 判断checked复选框是否有被选中 <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <script> window.onload () > {let odivdocument.getElementById("ant");let ckdocument.getElementById(&…

上班族如何当老板 五大模式任你选

中国教育在线讯 辞职创业&#xff0c;还是维持现在稳定的工作?这个是很多上班族都纠结过的问题&#xff0c;一边是稳定的工作和收入&#xff0c;一边是创业当老板的诱惑&#xff0c;真是很难选择。 其实&#xff0c;如果安排合理是可以“鱼与熊掌”兼得的&#xff0c;沈阳市古…

利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序

利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序 前面两篇文章已经介绍过 tap/tun 的原理和配置工具。这篇文章通过一个编程示例来深入了解 tap/tun 的程序结构。 01 准备工作 首先通过 modinfo tun 查看系统内核是否支持 tap/tun 设备驱动。 Copy[rootby ~]# modinfo tun f…

2020-3-21

题目一&#xff1a; JavaScript 获取月份最后一天日期 月份最后一天日期可能是不同的&#xff0c;比如有的是30、有的是31还有的是28。 <!DOCTYPE html><html> <head> <meta charset" utf-8"> <script type"text/javascript"&…

正方形矩阵求对角线之和

nint(input()) a[] for i in range(n): #循环体里面加入input&#xff08;&#xff09;可以实现一共执行n次input&#xff08;&#xff09; lst[int(x) for x in input().split()]a.append(lst) #用列表解析&#xff0c;两层列表代表行列&#xff0c;很巧妙的方法 w0 bl…

解决: Unable to connect to zookeeper server within timeout: 5000

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一个项目启动不起来了&#xff0c;报错如题&#xff1a; Caused by: org.I0Itec.zkclient.exception.ZkTimeoutException: Unable to c…

闲钱请看如何处理

买一点基金定投。基金是专家帮你理财。基金的起始资金最低单笔是1000元,定投200元起投 买基金到银行或者基金公司都行。银行能代理很多基金公司的业务&#xff0c;具体开户找银行理财专柜办理。现在有些证券公司也有代理基金买卖的。在银行开通网上银行后网上购买一般收费上有优…

JAVA 数组元素的反转

package Code411;/*数组元素的反转本来[1,2,3,4]反转后[4,3,2,1]1.对称位置的元素交换2.对称位子需要两个索引3.int temp a&#xff1b;ab;btemp;4.什么时候停止交换&#xff08;1&#xff09;minmax (2)min>max */public class CodeArrayReverse { public static void m…

requests模块相关用法

requests模块 -1. 什么是requests模块- python原生的一个基于网络请求的模块&#xff0c;模拟浏览器发起请求。 -2. 为什么使用requests模块-1. 自动处理url编码-2. 自动处理post请求参数-3. 简化cookie和代理的操作-3. requests模块如何被使用安装&#xff1a; pip install re…

2020-3-22

题目一&#xff1a; JavaScript 天小时分钟和秒倒计时 代码与解析&#xff1a; <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <style type"text/css"> *{margin:0;padding:0;list-style:none; } body{font-size:…

TeamViewer13 -- 安装、使用说明

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Teamviewer13是一款强大的远程桌面控制工具&#xff0c;同时也是一款非常实用的共享文件传输工具&#xff0c;它拥有简洁的界面以及方便快…

论程序员的自我修炼

摘要&#xff1a;软件开发是个挑战&#xff0c;尤其是对于那些完美主义的程序员。为了想要成为更好的程序员&#xff0c;总会开发出一些特别的功能&#xff0c;在软件设计上想要做到零瑕疵&#xff0c;但事实上&#xff0c;完美的软件设计是根本不存在的&#xff0c;试着让你的…

利用 Charles Proxy 下载旧版本 iOS App

一、软件准备 1、旧版本 iTunes1.IPSW Downloads&#xff1a;https://ipsw.me/2.百度网盘链接&#xff1a;https://pan.baidu.com/s/1PO9Z12o-rqZ_JG68zRqEnA 提取码&#xff1a;fe1v 2、抓包工具 Charles Proxy1.Charles官网链接&#xff1a;https://www.charlesproxy.com/2.百…

禅道8.2-9.2.1注入GetShell

漏洞分析附上某老哥的漏洞分析&#xff0c;来了解下原理。 漏洞利用查看版本&#xff1a;访问Url&#xff1a;http://127.0.0.1/zentao/index.php?modegetconfig即可获取禅道的版本号以及一些其他的信息&#xff0c;目前漏洞存在于v8.2~v9.2确定版本号之后&#xff0c;我们就…

2020-3-23

题目一&#xff1a; JavaScript 复选框全选和全不选 <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <style type"text/css"> body{font-size:12px;} ul{list-style:none} </style> <script type"te…

Maven 依赖-镜像仓库替换为 -- 阿里云镜像仓库(飞快实现 pom 引入)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 在本地 maven 的 setting 配置文件中加上阿里云镜像地址就行了&#xff1a; 新增配置内容&#xff1a; <!-- 阿里镜像仓库 --><…

cmake 常用命令

1. 使用日期 # 获取时间 string(TIMESTAMP DATE_TIME "%y-%m-%d %H:%M")# 获取日期 string(TIMESTAMP DATE_VERSION "%m%d") 转载于:https://www.cnblogs.com/ziyu-trip/p/10697309.html

爱屋吉屋病死后,链家、中原、我爱我家们却哭不得笑不得

作为互联网房产中介最快成长为行业独角兽的爱屋吉屋&#xff0c;还是没能迎来开春之暖&#xff0c;于2019年2月19日便停止了运营。对于这个享有创造中国房市273天四轮融资的奇迹、估值超过10亿美元的速成独角兽、一代“革命者”、创造世界纪录的互联网房产神话等多个美誉企业的…