(最后梳理比较简洁,在慢慢完善)
网上已有很多相关的js执行机制的文章了,那为啥还要写这个?
原因是其中一个机制大家有两套说法,不多BB直接上争议点 ↓
(不想看或已了解的直接跳到最后总结)
所以,我个人的理解是:宏任务便是 JavaScript 与宿主环境产生的回调,需要宿主环境配合处理并且会被放入回调队列的任务都是宏任务。
作者:Reed
链接:
来源:掘金
这里可能有小伙伴不清楚宿主环境的概念,我简单描述下:
宿主环境是作为js运行的一个载体,常见的有浏览器、node.js等。
我们进入正题,除了广义的同步任务和异步任务,我们对任务有更精细的定义:
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval
- micro-task(微任务):PromiseTick
作者:ssssyoki
链接:
来源:掘金
这个是笔者认同的,即:宏任务包含script主代码块
我觉得不能这样理解,首先宏任务和微任务的定义,都是异步的js语句。console.log明显是同步语句。一个js文件的执行,应该是主执行栈先执行同步语句,遇到异步语句,放入任务队列。之后执行微任务队列,然后从宏任务队列取出头部的宏任务执行,执行过程中会产生新的微任务队列。这样循环执行,直到宏任务和微任务全部执行完。eventloop
作者:爱吃橘子
链接:=tag-newest
来源:segmentfault思否
因为代码不是任务,所以 console.log()这句代码也不是任务,更不是宏任务。
虽然社区有人总喜欢列举 Promise.then、MutationObserver 是微任务(这里没列举完全),但是没捋清事件循环机制的前提下,死记硬背这些个“微任务”的话,面试官很容易借此挖坑请你跳。
所谓任务,浅显来说就是代码块开始执行的入口(确切地说,是函数栈的入口,但是栈的概念较为复杂,不表)。而在 JS 里,除了“script整体代码块”之外,所有代码块的入口都是“回调函数”,回调函数被注册到事件后不会马上被执行,而是保存在一个神秘的的地方,保存起来待执行的才能算“任务”,然后才有宏/微任务之分。
“script整体代码块”的特殊之处,在于它的入口不是回调函数,但是我们可以想象它被装在一个隐形的函数里,作为回调函数被注册到某个事件里(大概是它解析完成之后会触发的一个事件),这时候这个隐形的函数就成为了一个任务。
作者:madRain
链接:=tag-newest
来源:segmentfault思否
简单总结就是:异步代码才区分宏任务微任务
微任务和宏任务皆为异步任务,它们都属于一个队列,主要区别在于他们的执行顺序,Event Loop的走向和取值。那么他们之间到底有什么区别呢?
…
而宏任务一般是:包括整体代码script,setTimeout,setInterval、setImmediate。
微任务:原生Promise(有些实现的promise将then方法放到了宏任务中)、Tick、Object.observe(已废弃)、 MutationObserver
记住就行了。
作者:张倩qianniuer
链接:
来源:掘金
首先要说明宏任务其实一开始就是任务(task),为什么这么说呢?因为ES6新引入了Promise标准,同时浏览器实现上多了一个microtask微任务概念,作为对照才称宏任务。
贴上MDN文档定义
一个任务就是指计划由标准机制来执行的任何 JavaScript,如程序的初始化、事件触发的回调等。 除了使用事件,你还可以使用 setTimeout() 或者 setInterval() 来添加任务。
任务队列和微任务队列的区别很简单,但却很重要:
- 当执行来自任务队列中的任务时,在每一次新的事件循环开始迭代的时候运行时都会执行队列中的每个任务。在每次迭代开始之后加入到队列中的任务需要在下一次迭代开始之后才会被执行.
- 每次当一个任务退出且执行上下文为空的时候,微任务队列中的每一个微任务会依次被执行。不同的是它会等到微任务队列为空才会停止执行——即使中途有微任务加入。换句话说,微任务可以添加新的微任务到队列中,并在下一个任务开始执行之前且当前事件循环结束之前执行完所有的微任务。
由此可以得出结论:
宏任务是包含JS主代码块的。
从区别上还可以很明显看出js事件的循环机制,每次宏任务迭代开始后加入到任务队列中的宏任务要等到下一次任务迭代开始执行。
而微任务中途加入的也会在这次事件循环结束前执行完。
先介绍定义,熟悉的可以直接跳过,看目录中的 完整关系总结
首先要知道js是单线程脚本语言。// 尽管h5提出了worker,但他也是基于单线程实现的
同步是js任务进入任务栈按顺序等待主线程执行的过程,简单来讲就是js从上到下代码的运行的过程,如果中间有个同步任务出现了死循环,那么浏览器可能就会出现js无响应…意思就是无法继续向下执行。
但是我们读取本地文件数据,或者获取服务器接口数据时,花费的时间无法确定,难道之后的js代码就要一直等待吗?这样会导致页面看起来非常卡顿,严重影响用户体验。这个时候就出现了异步,即不进入主线程任务栈,而是先进入event Table并注册回调函数,然后按顺序进入异步事件队列,在主线程的任务栈执行完后调用(队列先进先出,所以按注册函数进入队列的顺序来调用)。
// 文字看的累没关系,可以配合流程图食用
进入任务栈等待主线程执行的主代码块,包括从异步队列里加入到栈的,如setTimeout()、setInterval()的回调,其中不含异步队列中的微任务如Promise.then回调。
此时注意事件循环中(event loop)从异步队列加入到栈的宏任务是作为下一个事件来执行的,由于GUI渲染线程机制,每次事件循环后都会进行页面渲染,如下图:
第一次宏任务完成 → 页面渲染 → 第一次宏任务完成(包含上一次宏任务事件时,异步队列中加入的宏任务) → 页面渲染…
常见宏任务有:
是异步队列中,在当前这一次宏任务执行完后,页面渲染之前要执行的任务。
此时注意,即使当前微任务执行过程中,产生了新的微任务,也会在下一个宏任务开始执行之前且当前事件循环结束之前执行完所有的微任务。
第一次宏任务 → 第一次所有微任务 → 页面渲染 → 第二次宏任务(包含上一次宏任务事件时,异步队列中加入的宏任务)→ 第二次所有微任务 → 页面渲染…
常见微任务有:
如果不理解,简单讲比如:A是当前页面script代码第一次执行事件,B是第二次事件
a.顺序执行同步任务
b.遇到异步任务
c.异步微任务,插入当前事件A队尾等待执行
异步宏任务,插入下次事件循环B排队执行
写的不咋样,哪里有问题请随意指出,或者有什么想讨论都可以留言,如果看不下去,点击
「硬核JS」一次搞懂JS运行机制看大佬的文章。觉得害行的点个赞鼓励一下呗。
辛苦各位看官,谢谢!
后续还会继续完善。
本文发布于:2024-01-31 14:11:17,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170668147629091.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |