宏任务、微任务和Event Loop

726 阅读4分钟

宏任务一般是:包括整体代码script,setTimeout,setInterval、setImmediate。

微任务:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick(Node.js 环境)、Object.observe(已废弃)、 MutationObserver

宏任务和微任务的区别 通俗易懂点的解释: 这个就像去银行办理业务,先要取号进行排号

柜员同时只能处理一个来办理业务的客户,这时每一个来办理业务的人就可以认为是银行柜员的一个宏任务来存在的。 当柜员处理完当前客服的问题以后,选择接待下一位,也就是下一个宏任务的开始

所以多个宏任务合在一起就可以认为说有一个任务队列在这,里面是当前银行中所有排号的客户。

任务队列中的都是已经完成的操作,而不是说注册一个异步任务就会被放在这个队列中,就像在银行排号,如果叫到你的时候你不在,那么你当前的号牌就作废了,柜员会直接跳过去进行下一个客户的业务处理,等你回来以后还要重新取号

一个宏任务在执行过程中是可以添加微任务的 ,就像在柜台办理业务,你前边的大爷可能在存款,在存款这个业务办理完以后,柜员就会问:还有没有其他需要办理的业务,然后大爷有办一些理财。 所以本来快轮到你来办理业务,会因为大爷临时添加的”理财业务“而往后推 无论是什么需求,只要是柜员能够帮他办理的,都会在处理你的业务之前来做这些事情,这些都可以认为是微任务。

这就说明: 在当前的微任务没有执行完时,是不会执行下一个宏任务的

举个栗子

image.png

打印顺序 1 => 2 => 3=> 4

setTimeout是宏任务, 而Promise.then则是具有代表性的微任务 所有会进入的异步都是指的事件回调中的那部分代码 也就是说new Promise在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行的(同步任务优先于异步任务执行) 举个栗子

image.png

举个栗子

image.png

打印顺序 Promise1 => Promise2 =>setTimeout1

promise参数中的promise1是同步执行的,其次是proimse微任务,在同步任务执行完后去清空微任务,最后清空完微任务再去宏任务队列取值

举个栗子

image.png

打印顺序 promise1 => setTimeout1 => promise2 => setTimeout2 这种嵌套的情况 一开始执行栈的同步任务执行完毕,去执行微任务,输入promise1 去宏任务队列查看,输出 setTimeout1, 执行setTimeout1时,会生成promise2的一个微任务,然后执行微任务列表,输出promise2 清空完微任务,就又会去宏任务队列取,这次输出setTimeout2

最后一个栗子,看下自己是否真正掌握了js的执行机制

image.png

打印顺序 1 => 7 => 6 => 8 => 2 => 4 => 3 => 5 => 9 => 11 => 10 => 12

第一轮循环 整体script作为一个宏任务进入主线程,遇到console.log,输出1 遇到setTimeout,回调函数分到宏任务,不输出,暂记setTimeout1 遇到process.nextTick(),回调函数分到微任务,记为process1 遇到promise,new promise直接执行,输出7, then分到微任务,纪为then1 又遇到setTimeout,回调函数分到宏任务,不输出,暂记setTimeout2

image.png 上图是第一轮循环宏任务结束时,此时已经输出1 7

发现还有process1和then1两个微任务 输出 6 8 于是,第一轮循环之后,输出 1 7 6 8

第二轮循环 从setTimeout1宏任务开始 首先输出2,遇到process,nextTick(),分到微任务,记为 process2 new promise 立即执行 ,输出4,then分到微任务,记为then2

image.png

于是 第二轮循环之后,输出 2 4 3 5

最后,第三轮循环,同第二轮 输出 9 11 10 12

那Event Loop呢??

上面讨论到的宏任务 微任务,各种任务的执行 js是单线程的语言,同一个时间不能处理多个任务,就像 每办理完一个业务,柜员就会问当前的客户,是否还有其他需要办理的业务。(检查还有没有微任务需要执行) 在客户告知没有事情以后,柜员就去查看后边有没有等着办理业务的人。(结束本次宏任务,检查还有没有宏任务需要处理) 这个检查的过程是持续进行的,每完成一个任务都会进行一次,而这样的操作就被称作Event Loop (这是非常简易的描述,实际上会复杂很多)

各位大佬,有不足请指出~~~