Javascript 同步,异步:微任务和宏任务

1.javascript是单线程的语言

javascript是一门单线程执行的编程语言。也就是说,同一时间只能做一件事情。

如下:如果有多个任务要执行,执行其他任务时,其他任务都要进行等待

52.png

1.1 单线程执行任务队列的问题

如果前一个任务非常耗时,则后续的任务不得不一直等待,从而导致程序假死的问题。

2.同步任务和异步任务

为了防止某个耗时任务导致程序假死的问题,javascript把待执行的任务分为了两类。

  • 同步任务
  • 又叫做 非耗时任务,指的是在主线程上排队执行的那些任务
  • 只有前一个任务执行完毕,才能执行后一个任务
  • 异步任务
  • 又叫做 耗时任务,异步任务由javascript委托给宿主环境进行执行
  • 当异步任务执行完成之后,会通知javascript主线程执行异步任务的回调函数
2.1 同步任务和异步任务的执行过程

53.png

  • 同步任务由javascript主线程次序执行
  • 异步任务委托给宿主环境执行
  • 已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行
  • javascript主线程的执行栈被清空后,会读取任务队列中的回调函数,次序执行。
  • javascript主线程不断重复上面的第4步

js的主线程会从自己的执行栈中去执行栈中的所有任务,当发现任务是同步任务时,js会自己进行执行。如果是异步任务,会委托给宿主环境执行。当js发现自己的执行栈中被执行完后,会从任务队列中按顺序把对应的回调函数取出来放入栈中,按顺序执行。

3.EventLoop的基本概念

javascript 主线程从“任务队列”中读取异步任务回调函数,放到执行栈中依次执行 。这个过程是循环不断的,所以整个的这种运行机制又称为EventLoop(事件循环)。

3.1 结合EventLoop分析输出顺序
import Fs from "fs";
console.log("A");

Fs.readFile("./files/ce.txt","utf8").then(res=>{console.log("B");})
setTimeout(()=>{
  console.log("C");
},0)

console.log("D");

最终的结果是 A D C B

  • 因为主线程上只有A和D,是同步任务,所以会依次执行,而B、C是异步任务让js委托给宿主环境执行。
  • 然后定时器,只是延时了0秒,所以就会让宿主环境立即执行,然后返回一个回调函数,等主线程空闲时执行。

4.宏任务和微任务

javascript对异步任务又做了进一步的划分,分为了两类,

宏任务(macrotask)
  1. 异步Ajax请求
  2. setTimeOut、setInterval
  3. 文件操作
  4. 其他宏任务
微任务(microtask)
  1. Promise.then、.catch、和.finally
  2. process.nextTick
  3. 其他微任务

在这里插入图片描述

4.1 宏任务和微任务的执行顺序

55.png

每个宏任务执行完后,都会检查是否存在待执行的微任务
如果有,则会将所有待执行的微任务执行完,再执行下一个宏任务
宏任务和微任务是交替执行的

4.2 根据宏任务和微任务分析代码输出的顺序
setTimeout(()=>{
  console.log(1);
})

new Promise(function(resolve){
  console.log(2);
  resolve()
}).then(res=>{
  console.log(3);
})

console.log(4);

最后的结果是 2 4 3 1

  • setTimeout是一个宏任务, new Promise()是一个同步任务,.then()是一个微任务
  • console.log(4)是一个同步任务 所以执行的顺序是:执行的准则是
  • 先执行同步任务,再去任务队列中读取回调函数放入执行栈中,按次序执行。但异步任务中:先执行微任务,再执行宏任务
  1. new Promise()操作
  2. console.log(4)
  3. .then()
  4. setTimeout
4.3 经典面试题

56.png

先来分析同步任务和异步任务,最后来分析异步任务中的宏任务和微任务

  • 第1行是同步任务1
  • 第3-10行是异步任务1(宏任务)
  • 第12-15行是同步任务2,也就是new Promise()这一部分
  • 第15-17行是异步任务2(微任务)
  • 第20-28行是异步任务3(宏任务)

所以执行顺序是:同步任务js本身自身处理,而异步任务交给宿主环境执行

js本身处理的过程:

  • 执行同步任务1 :输出1
  • 执行同步任务2:输出 5
  • 同步任务执行完
  • 从任务队列中取出执行完对应的回调函数,放入执行栈中,依次执行

宿主环境处理的过程:

  • 先执行异步任务2,执行异步任务2,并返回到任务队列中,待主线程执行 输出 6
  • 看是否存在待执行的微任务,发现没有,按次序执行宏任务
  • 先执行 异步任务1 ,并返回到任务队列中,待主线程执行输出 2 3 4
  • 在执行异步任务3 并返回到任务队列中,待主线程执行输出 7 8 9

所以总的输出结果是: 1 5 6 2 3 4 7 8 9

5.总结

总结:同步—>微任务—>宏任务

console.log(1)
process.nextTick(() => { // 微任务
  console.log(8)
  setTimeout(() => {
    console.log(9)
  })
})
setTimeout(() => { // 宏任务
  console.log(2)
  new Promise(() => {
    console.log(11)
  })
})
// 特殊说明: new Promise()属于主线程任务
let promise = new Promise((resolve,reject) => {
  setTimeout(() => {
    console.log(10)
  })
  resolve()
  // 这个console也属于主线程任务
  console.log(4)
})
fn()
console.log(3)
promise.then(() => { //微任务
  console.log(12)
})
function fn(){
  console.log(6)
}

结果是1、4、6、3、12、8、2、11、10、9

在这里插入图片描述

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
微任务宏任务是在JavaScript中用于管理异步操作的两种不同的执行机制。 微任务(Microtask)是一个相对较小的任务,通常是由Promise对象的回调函数产生的。当一个Promise对象被resolve或reject时,与该Promise相关联的微任务会被添加到微任务队列中等待执行。微任务的执行时机一般在当前任务执行结束后,下一个事件循环之前。常见的微任务包括Promise的回调函数、MutationObserver的回调函数等。 宏任务(Macrotask)是一个相对较大的任务,通常由浏览器提供的API触发,例如setTimeout、setInterval、requestAnimationFrame等。当宏任务被触发时,相关的任务会被添加到宏任务队列中等待执行。宏任务的执行时机一般在当前事件循环结束后,下一个事件循环开始时。 区别总结如下: - 微任务是相对较小的任务宏任务是相对较大的任务。 - 微任务的执行时机在当前任务执行结束后,下一个事件循环之前;宏任务的执行时机在当前事件循环结束后,下一个事件循环开始时。 - 微任务的优先级高于宏任务,即微任务会在宏任务之前执行。 - 微任务包括Promise的回调函数、MutationObserver的回调函数等;宏任务包括setTimeout、setInterval、requestAnimationFrame等。 需要注意的是,微任务宏任务的执行顺序是有区别的,具体执行顺序可以参考相关规范(例如HTML规范或JavaScript规范),不同浏览器也可能有差异。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值