事件循环进阶:macrotask与microtask
这段参考了参考来源中的第2篇文章(英文版的),(加了下自己的理解重新描述了下),
这里没法给大家演示代码,我就简单说下我的理解吧。
promise和settimeout 在一起的时候执行顺序是个有意思的事儿,
为什么呢?因为Promise里有了一个一个新的概念:microtask
或者,进一步,JS中分为两种任务类型:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task
它们的定义?区别?简单点可以按如下理解:
macrotask(又称之为宏任务),可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)
每一个task会从头到尾将这个任务执行完毕,不会执行其它
浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个 task 执行开始前,对页面进行重新渲染
(`task->渲染->task->...`)
microtask(又称为微任务),可以理解是在当前 task 执行结束后立即执行的任务
也就是说,在当前task任务后,下一个task之前,在渲染之前
所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染
也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)
分别很么样的场景会形成macrotask和microtask呢?
macrotask:主代码块,setTimeout,setInterval等(可以看到,事件队列中的每一个事件都是一个macrotask)
microtask:Promise,process.nextTick等
__补充:在node环境下,process.nextTick的优先级高于Promise__,也就是可以简单理解为:在宏任务结束后会先执行微任务队列中的nextTickQueue部分,然后才会执行微任务中的Promise部分。
再根据线程来理解下:
macrotask中的事件都是放在一个事件队列中的,而这个队列由事件触发线程维护
microtask中的所有微任务都是添加到微任务队列(Job Queues)中,等待当前macrotask执行完毕后执行,而这个队列由JS引擎线程维护(这点由自己理解+推测得出,因为它是在主线程下无缝执行的)
所以,总结下运行机制:
执行一个宏任务(栈中没有就从事件队列中获取)
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
另外,请注意下
Promise的polyfill与官方版本的区别:官方版本中,是标准的microtask形式
polyfill,一般都是通过setTimeout模拟的,所以是macrotask形式
请特别注意这两点区别
注意,有一些浏览器执行结果不一样(因为它们可能把microtask当成macrotask来执行了),
但是为了简单,这里不描述一些不标准的浏览器下的场景(但记住,有些浏览器可能并不标准)
好了,到这里咱们这个从浏览器到多进程到多线程到js单线程到js运行机制就讲完了。内容还算是比较全面,不足的就是只能听么有代码参考。
不过没关系,大家可以根据我提到的知识点自己再进行深入的学习,或者关注下我个人的公众号-重度前端,我讲的内容都有文字版在上面而且有代码,另外我记录了一些我平时看到的比较好的 有深度的文章,还有一些原创内容。直接微信 搜 重度前端。
好了,今天就到这里了。后面计划下分享哪些有意思的东西,咱们下次见。
事件循环进阶:macrotask与microtask的更多相关文章
- c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)
c#封装DBHelper类 public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...
- JavaScript 事件循环及异步原理(完全指北)
引言 最近面试被问到,JS 既然是单线程的,为什么可以执行异步操作? 当时脑子蒙了,思维一直被困在 单线程 这个问题上,一直在思考单线程为什么可以额外运行任务,其实在我很早以前写的博客里面有写相关的内 ...
- js事件循环
之前有看过一些事件循环的博客,不过一阵子没看就发现自己忘光了,所以决定来自己写一个博客总结下! 首先,我们来解释下事件循环是个什么东西: 就我们所知,浏览器的js是单线程的,也就是说,在同一时刻,最多 ...
- 浏览器与Node的事件循环(Event Loop)有何区别?
前言 本文我们将会介绍 JS 实现异步的原理,并且了解了在浏览器和 Node 中 Event Loop 其实是不相同的. 一.线程与进程 1. 概念 我们经常说 JS 是单线程执行的,指的是一个进程里 ...
- JS 事件循环机制 - 任务队列、web API、JS主线程的相互协同
一.JS单线程.异步.同步概念 从上一篇说明vue nextTick的文章中,多次出现“事件循环”这个名词,简单说明了事件循环的步骤,以便理解nextTick的运行时机,这篇文章将更为详细的分析下事件 ...
- JavaScript 事件循环
JavaScript 事件循环 事件循环 任务队列 async/await 又是如何处理的呢 ? 定时器问题 阻塞还是非阻塞 实际应用案例 拆分 CPU 过载任务 进度指示 在事件之后做一些事情 事件 ...
- 面试一定会问到的-js事件循环
这篇文章讲讲浏览器的事件循环(nodejs中的事件循环稍有不同),事件循环是js的核心之一,因为js是单线程,所以异步事件实现就是依赖于事件循环机制,理解事件循环可让我们更清晰的处理js异步事件和应对 ...
- event loop js事件循环 microtask macrotask
转: 原文 http://blog.csdn.net/sjn0503/article/details/76087631 ---------------------------------------- ...
- 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
随机推荐
- myEclipse修改字体大小
- openerp学习笔记 对象继承,对象初始化数据
1.对象继承 _inherit = "product.product" 继承产品对象,给产品对象添加字段或方法,不需要设置 _name._table 等属性 注意: ...
- 当页面有多个js文件时,应如何引入?
1. 我们知道如果一个页面有多个js文件,并且这些js文件有的还有依赖关系的时候,我们就要特别注意他们之间的引入顺序,否则就会报错. 如:一个js文件依赖jquery,我们就要先引入jquery,然后 ...
- orcale 之 存储过程
之前我们学习过 PL/SQL, 那么当我们的工作中我们通过 PL/SQL 做很多的事情,那么有一个问题,在每次的座同样一件事的时候是不是都需要重新通过 PL/SQL 去完成呢?可不可以只写一次然后,在 ...
- Android新手常见问题(一)
[1]AAPT2 error: check logs for details File->Settings->Build->Gradle一看path里有中文 最根本的原因是因为use ...
- WPF Window对象的生命周期
WPF中所有窗口的基类型都是System.Windows.Window.Window通常用于SDI(SingleDocumentInterface).MDI(MultipleDocumentInter ...
- 前端渲染模板(一):Thymeleaf
一.使用 本篇文章将以SpringBoot为框架来介绍Thymeleaf的用法. 1 资源文件的约定目录结构 Maven的资源文件目录:/src/java/resources spring-boot ...
- 【分布式消息队列-MQ】
http://www.cnblogs.com/itfly8/p/5155983.html
- angularjs之UI Grid 的刷新 本地数据源及HTTP数据源
关键代码: 如果数据源是本地数据$("#hidJsonData").val("[]"); var myJsonData = []; if ($(&quo ...
- B/S结构中页面间的传值
常见的页面间的传值有session,cookie,application,server.transfer(),queryString,今天主要记录一下server.transfer()的用法. 从A页 ...