event loop一篇文章足矣
event loop
浏览器内核是多线程,
Javascript
是单线程。
楼主之前讲解了js
的异步处理,只是讲解了异步处理的方法,但是对于异步处理的原理还是不是很了解,这篇文章是对于浏览器的线程方面对JavaScript
的运行机制进行分析。
1:浏览器基本
我们经常说,js
的执行环境是一个单线程,会按顺序执行代码,但是JavaScript
又是可以异步,这两者感觉有冲突,但是本质上,如果理解浏览器的事件循环机制(event loop),就会觉得并不冲突。
浏览器里面不仅只有解释JavaScript
的引擎,还包括很多其它的引擎。
浏览器主要包括:
- 用户界面:包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
- 浏览器引擎(浏览器内核): 在用户界面和呈现引擎之间传送指令。
- 呈现引擎 - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
- 网络 - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
- 用户界面后端 - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
- JavaScript 解释器。用于解析和执行 JavaScript 代码。
- 数据存储。这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了“网络数据库”,这是一个完整(但是轻便)的浏览器内数据库。
我们今天主要讨论的是浏览器引擎(浏览器内核)和 JavaScript 解释器(V8引擎)之间的交互和沟通。
2:浏览器引擎(浏览器内核)
浏览器内核的是一个多线程处理,它主要包含如下几个线程
- GUI渲染线程: 渲染页面的
html
元素 - JavaScript引擎线程: 页面的交互和
dom
渲染 - 定时触发器线程:一定时间后,来触发对应的线程
- 事件触发线程:当一个事件触发该线程的时候,就会把它放到js的事件队列中等待执行。常用于异步操作。
- 异步http线程: 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理。
他们之间有一下的联系:
- JavaScript引擎和GUI引擎互斥,不能一边操作
dom
一边渲染页面 - JavaScript引擎是单线程,所有需要按照事件处理队列来处理相应的代码。
- JavaScript引擎有一个监听事件(monitoring process)的功能,会持续不断的检查
js
引擎的主线程执行栈是否为空,如果为空就会去取事件触发线程存放在事件队列中的回调函数执行。
3:js引擎执行机制
由于js的运行环境是单线程的,一些异步操作还是需要借助于浏览器这个宿主来实现。这里简单的一个图来描述js
运行的时候的流程。主要运用了浏览器的js引擎线程和事件触发线程,有时候开启网络服务和定时器也会用到其他的线程。
4: micro task 和 macro task
浏览器的事件循环依靠已事件队列,但是一个进程中不止一个事件队列,大致可以分为micro task
和macro task
,常见的微任务和宏任务分别包括:
micro task :
- nextTick
- callback
- Promise
- process.nextTick
- Object.observe
- MutationObserver
macro task:
- setTimeout
- setInterval
- I/O
- script代码块
主要部分: 事件队列在同步队列执行完后,首先会执行nextTick,等nextTick执行完成后,然后会先执行micro task, 等micro task队列空了之后,才会去执行macro task,如果中间添加了micro task加入了micro task队列,会继续去执行micro task队列,然后再回到macro task队列。js引擎存在monitoring process进程, 会不停的监听task queue
它们的细节可以参考Tasks和Microtasks
5:event loop和宏任务、微任务
一段代码块就是一个宏任务。所有一般执行代码块的时候,也就是程序执行进入主线程了,主线程会根据不同的代码再分微任务和宏任务等待主线程执行完成后,不停地循环执行。
主线程(宏任务) => 微任务 => 宏任务 => 主线程
下图是一个简易的时间循环:
6: 简易的event loop
console.log('start') Promise.resolve().then((resolve) => { console.log(1) })) console.log('end')
大致流程:
- 这一个代码块相当于一个macro-task,进入主线程。
- 遇到同步的代码
console.log('start')
开始执行 Promise
是micro-task,把它的回调函数放入微任务Event Queue中- 遇到
console.log
开始执行,执行完后,这个代码块宏任务完成,js
监听进程发现主线程空了,就会去寻找微任务。 - 去微任务Event Queue找到Primise的回调函数,执行。
图解浏览器内部执行:
7:复杂的分析
这里我们通过2个复杂的代码来检验是否已经基本了解了事件循环的机制:
// 来至于谷友的一到面试题
<script>
async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { console.log('async2'); } console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); async1(); new Promise(function(resolve) { console.log('promise1'); resolve(); }).then(function() { console.log('promise2'); }); console.log('script end'); </script>
整个代码块作为一个宏任务,进入主线程
看到函数申明但没有执行,遇到函数console.log执行,输出
script start
遇到
setTimeout()
,把它的回调函数放入宏任务(setTimeout1)。宏任务 微任务 setTimeout1 遇到执行
async1()
, 进入async
的执行上下文之后,遇到console.log
输出async1 start
然后遇到
await async2()
,由于()
的优先级高,所有先执行async2()
,进入async2()
的执行上下文。看到
console.log
输出async2
,之后没有返回值,结束函数,返回undefined
,返回async1
的执行上下文的await undefined
,由于async
函数使用await
后得语句会被放入一个回调函数中,所以把下面的放入微任务中。宏任务 微任务 setTimeout1 async1=> awati 后面的语句 结束
async1
,返回全局上下文,遇到Promise
构造函数,里面的函数立马执行, 输出promise1
, 之后的回调函数进入微任务宏任务 微任务 setTimeout1 async1=> awati 后面的语句 new Promise() => 后的then 执行完Promise(),遇到console.log,输出
script end
,这里一个宏任务代码块执行完毕。在主线程执行的过程中,事件触发线程会一直监听异步事件,当异步事件处理完成后,把它的回调函数放入事件队列,等待执行。
主线程现在空闲下来后,执行事件队列中的微任务,然后继续向下执行,遇到
new Promise()
后面的回调函数,执行代码,输出promise2
(这里2个微任务的优先级,promise高于async)。看到
async1
中await
后面的回调函数,执行代码,输出async1 end
宏任务 微任务 setTimeout1 空 此时微任务中的队列为空,开始执行队列中的宏任务,进入一个新的代码块。遇到
console.log
,输出setTimeout
执行完成,最后结果为
```javascript
script start => async1 start => async2 => promise1 => script end => promise2 => async1 end => setTimeout ```
8:总结
- JavaScript运行环境是单线程,不管什么代码,什么框架的异步代码,都是利用宿主对象(Node,浏览器)的其他线程来通过事件循环机制实现
- 我们一般说的运行和执行是不一样的,JavaScript的运行环境是JavaScript解析引擎,执行环境比如node,浏览器。
- JavaScript解析引擎会监听事件循环机制,把异步任务放入事件队列。
链接参考:
这一次,彻底弄懂 JavaScript 执行机制
图形制作软件
从Promise来看JavaScript中的Event Loop、Tasks和Microtasks
Js 的多宿主时代
转载于:https://www.cnblogs.com/zhilin/p/11411599.html
event loop一篇文章足矣相关推荐
- 全面了解苹果WWDC2020,一篇文章足矣
WWDC2020已经落下帷幕,如果你想要了解昨夜究竟发生了什么,那么看这一篇文章就足够了!WWDC是苹果公司年度的开发者大会,从公司战略的层面来讲,其战略意义远胜于苹果秋季新品发布会.苹果的电子产品之 ...
- 跟着 Event loop 规范理解浏览器中的异步机制
原文发自我的 GitHub blog,欢迎关注 前言 我们都知道 JavaScript 是一门单线程语言,这意味着同一事件只能执行一个任务,结束了才能去执行下一个.如果前面的任务没有执行完,后面的任务 ...
- 【转载】浏览器事件循环机制(event loop)
首先,本文转自https://juejin.im/post/5afbc62151882542af04112d 当我看完菲利普·罗伯茨的 javascript event loop的演讲的时候,就对于事 ...
- [前端漫谈_4] 从 薛定谔的猫 聊到 Event loop
前言 上次我们从高阶函数聊到了 promise ,这次我们聊聊: 从 promise A+ 规范和 promise 应用来看 promise 的特性 promise 和 eventloop 的关系 从 ...
- 你不知道的Event Loop
关于Event Loop网上有很多文章都有讲解,包括我自己也有几篇文章有讲述event loop相关内容.之前写了一篇文章总结了Nodejs中event loop的原理,这里的event loop指的 ...
- 一次弄懂Event Loop(彻底解决此类面试问题)
前言 Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理. 为啥要弄懂Event Loop 是要增加自己技术 ...
- 从 薛定谔的猫 聊到 Event loop
前言 上次我们从高阶函数聊到了 promise ,这次我们聊聊: •从 promise A+ 规范和 promise 应用来看 promise 的特性•promise 和 eventloop 的关系 ...
- JavaScript基础:浅聊事件循环(Event LooP)以及微任务,宏任务,DOM渲染
一直说JavaScript是单线程的执行的(当然也可以通过其它其它的方式异步,本篇暂时不聊). 内核的组成 首先聊一下浏览器的内核组成部分,当然下面也不是全部,而只是说一些常见的. 主线线程 js引擎 ...
- UML科普文,一篇文章掌握14种UML图
前言 上一篇文章写了一篇建造者模式,其中有几个UML类图,有的读者反馈看不懂了,我们今天就来解决一哈. 什么是UML? UML是Unified Model Language的缩写,中文是统一建模语言, ...
最新文章
- EditText的另类用法
- python入门作业编程题-python入门(一)作业
- jquery 时间操作
- DEEPNORM:千层transformer...
- 2014\Province_C_C++_B\1 啤酒和饮料
- 线程池的简单创建和实现
- Composer快速入门
- 字体小于12px解决办法
- pytorch clamp 与clamp_区别
- ssd颗粒查看工具_贴吧机佬强烈推荐的游戏SSD?西数蓝盘3D M.2 500G实测
- 深度学习与自然语言处理 主要概念一览
- 使用MHA对mysql主从架构中的主节点做高可用
- 超好用的Redis管理及监控工具,使用后可大大提高你的工作效率!
- 随便谈谈alphago与人机大战
- WebRTC音频处理流程简介
- 2022年茶艺师(初级)考试试卷及茶艺师(初级)模拟试题
- 高斯法计算矩阵的行列式
- 基于bert的platos republic i ii情绪分析和可视化
- 使用visio创建跨职能流程图
- Program received signal SIGSEGV
热门文章
- mysql语法_MySql实用技能,最常用的删除语法
- mysql 存储过程创建表_MySQL之存储过程按月创建表的方法步骤
- 二级c语言 考生文件夹下,二级C语言上机新题库.doc
- java 打包工具_Java打包Windows安装程序
- 阿里云服务器安装docker开发环境
- java jackson_Jackson 框架的高阶应用
- 照片浏览器_2020护考报名失败!只因照片太大瞎忙乎三小时...
- 设计一个扩展自抽象类geometricobject_设计模式4之模板方法模式
- python可以用vs编辑吗_在VS2017中编写Python程序
- linux 学习笔记 -vim 操作