谈谈对js单线程,宏任务微任务理解

在前端的面试中经常会问到关于代码执行顺序的问题,我们先看下面一段代码

setTimeout( () => console.log(4))
 
new Promise(resolve => {
  resolve()
  console.log(1)
}).then( () => {
  console.log(3)
})
 
Promise.resolve(5).then(() => console.log(5))
 
console.log(2)

问题是:在浏览器上面 1 2 3 5 4的打印的顺序。

上面这个问题看起来对有的同学可能很简单,到有的同学可能会比较复杂。对你不管是复杂还是简单,这其中涉及到的只是点都是一样的。JavaScript单线程,宏任务与微任务。这些就是这个题目的考点,理解了这些,那么上面的这道题对你来说那就是信手拈来,游刃有余。

JavaScript中的单线程

JavaScript是单线程脚本语言。所以,在一行代码的执行过程过,必然不会执行另一行代码的,就行你在使用了alert(1)以后在后面疯狂的console.log(),如果执行到 alert(1),你没有关闭这个弹窗,后面的console.log()是永远都不会执行的,因为 alert() 这个任务还没有执行完成,下面的代码没法执行。通俗一点就是:如果你去食堂打饭,前面排了很长的队,如果你想要打到饭,那么你需要等前面的小可爱都能够顺利的打完饭才可以,你是不能够插队的。那什么是宏任务,什么又是微任务呢?

同样是打饭的例子,你要打饭这件事请就是宏任务。这是一个大的事件。当轮到你打饭的时候,事件执行到你这里了,这个时候阿姨开始给你打饭,后面的同学还在等待着。但是你去打饭不单单的就是打饭,你会询问每种菜是什么,价格是多少,有没有XXX菜,有没有汤一样,那这些询问可以比作是微任务。当你的宏任务与微任务都执行完成了,相当于你的这一轮时间执行完成,这个时候开始执行下一轮事件,也就是下一个同学开始打饭了。同样的,下面的一轮循环中也可能存在微任务。

通过上面的例子,如果能有大概的明白了什么是宏任务,什么是微任务了。

宏任务

macrotask,也叫 tasks,主要的工作如下:

创建主文档对象,解析HTML,执行主线或者全局的javascript的代码,更改url以及各种事件。
页面加载,输入,网络事件,定时器。从浏览器角度看,宏任务是一个个离散的,独立的工作单元。
运行完成后,浏览器可以继续其他调度,重新渲染页面的UI或者去执行垃圾回收
一些异步任务的回调会以此进入 macrotask queue(宏任务队列),等等后续被调用,这些异步函数包括:

  1. setTimeout
  2. setInterval
  3. setImmediate (Node)
  4. requestAnimationFrame (浏览器)
  5. I/O
  6. UI rendering (浏览器)

微任务

microtask,也叫 jobs,注意的工作如下:

微任务是更小的任务,微任务更新应用程序的状态,但是必须在浏览器任务继续执行其他任务之前执行,浏览器任务包括重新渲染页面的UI。
微任务包括Promise的回调函数,DOM发生变化等,微任务需要尽可能快地,通过异步方式执行,同时不能产生全新的微任务。
微任务能使得我们能够在重新渲染UI之前执行指定的行为,避免不必要的UI重绘,UI重绘会使得应用状态不连续
另一些异步回调会进入 microtask queue(微任务队列) ,等待后续被调用,这些异步函数包括:

  1. process.nextTick (Node)
  2. Promise.then()
  3. catch
  4. finally
  5. Object.observe
  6. MutationObserver

注意: 这里有一点需要注意的:Promise.then() 与 new Promise(() => {}).then()
是不同的,前面的是一个微任务,后面的 new Promise() 这一部分是一个构造函数,这是一个同步任务,后面的 .then()
才是一个微任务,这一点是非常重要的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值