宏任务和微任务JS执行顺序题目+总结

文章详细阐述了JavaScript中的事件循环机制,包括同步任务和异步任务的处理,重点讨论了宏任务(如setTimeout)和微任务(如Promise.then)的执行顺序。通过示例解释了async/await的用法,并提供了多个面试题来帮助读者加深对宏任务和微任务执行顺序的理解。文章还提到了process.nextTick和setImmediate在不同环境中的行为差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

宏任务和微任务

resolve(传的参数)标记成功,会调用promise.then

练习网站:

关于promise深入理解太长没来及看 博客文章:

promise本身是同步的,then/catch的回调函数是异步的

直接做题加深理解

这个是前端pink老师

事件循环eventloop

视频地址:
在这里插入图片描述

有些任务是耗时的,会阻塞代码的运行。比如中间有定时器,鼠标点击事件等

因此引出同步任务和异步任务

js执行栈的代码立即执行 返回结果

异步任务放到宿主环境中,等待正确的时机,推送到任务队列中【里面放着回调函数】

总结:

  • js是单线程,防止代码阻塞。任务分为同步任务和异步任务
  • 同步任务给js引擎执行,异步任务交给宿主环境【多线程】
  • 同步代码放到执行栈中,异步代码等待时机成熟推送到任务队列中排序
  • 执行栈执行完毕,会去任务队列中查看是否有异步代码,有就送到执行栈中执行,反复循环查看执行,这个过程叫事件循环。

宏任务和微任务

es5后引入了promise,不需要浏览器,js引擎也可以发起异步任务了
在这里插入图片描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MivaNQek-1672920007857)(imgs/image-20230105160043329.png)]

执行顺序

在这里插入图片描述

这个是晓舟报告 up主

视频链接
微任务在DOM渲染前,宏任务在DOM渲染后,所以微任务比宏任务先执行
在这里插入图片描述
执行顺序:
在这里插入图片描述
async和await

async/await会返回一个promise对象

// async function fun(){
//   return 1
// }
等价于
function fun() {
  return new Promise(resolve => {
    resolve(1)
  })
}

fun().then(data => {
  console.log(data)
})

//这样才可以获取值为1 

let p1 = new Promise(resolve => {
  resolve(1)
})
let p2 = new Promise(resolve => {
  resolve(2)
})
async function fun() {
  let a = await p1
  let b = await p2
  console.log(a, b) //1,2
}
fun()

await之后的代码可以理解为then中执行的代码

async function fun1() {
  let data = await fun2()
  console.log(data) //then中执行的代码
}
async function fun2() {
  console.log(200)
  return 100
}
fun1()
//200 100

例子-----后面题目也有这个例子:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDamwPx6-1672920616649)(imgs/image-20230105192332038.png)]

总结:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BxngPcG5-1672920567577)(imgs/image-20230105192558831.png)]

常见面试题

题目1.

直接理解

const myPromise = Promise.resolve(Promise.resolve('Promise'))

function funcOne() {
  setTimeout(() => console.log('Timeout 1!'), 0)
  myPromise.then(res => res).then(res => console.log(`${res} 1!`))
  console.log('Last line 1!')
}

async function funcTwo() {
  const res = await myPromise
  console.log(`${res} 2!`)
  setTimeout(() => console.log('Timeout 2!'), 0)
  console.log('Last line 2!')
}

funcOne()
funcTwo()

//输出结果
Last line 1!
Promise 2!
Last line 2!
Promise 1!
Timeout 1!
Timeout 2!

题目2.

const myPromise = Promise.resolve(Promise.resolve('Promise11111!'))

function funcOne() {
  myPromise.then(res => res).then(res => console.log(res + 'cc'))
  setTimeout(() => console.log('Timeout!111'), 0)
  console.log('Last line!111111')
}

async function funcTwo() {
  const res = await myPromise
  console.log((await res) + 'res')
  setTimeout(() => console.log('Timeout!222'), 0)
  console.log('Last line!2222222')
}

funcOne()
funcTwo()
//输出结果
Last line!111111
Promise11111!cc
Promise11111!res
Last line!2222222
Timeout!111
Timeout!222

题目3 3-6

题目3- 6来源于b站https://www.bilibili.com/video/BV1xe4y147ZB/?
在这里插入图片描述

结果是 3 2 1

resolve只是标记成功 里面的状态改变了 ,还是会继续往下执行

题目4.

在这里插入图片描述

结果是 11 14 12 15 13

题目5:

在这里插入图片描述

结果是:2 3 6 P2 P1 1 4 5

题目6:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h6lk5nyq-1672919648987)(imgs/image-20230105165501511.png)]

结果是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cKuOQSZA-1672919648989)(imgs/image-20230105165942599.png)]

注意:

await是右结合,右边代码执行完了才会执行下面的函数。await之后的代码都是微任务 ,放到异步队列中!!!

题目7:晓舟报告 ❌

视频来源
在这里插入图片描述

setImmediate(() => {
  console.log(1)
})
console.log(2)
setTimeout(() => {
  console.log(3)
}, 0)
setTimeout(() => {
  console.log(4)
},100)
console.log(5)
new Promise(resolve => {
  console.log(6)
  resolve()
}).then(() => {
  console.log(7)
})
process.nextTick(() => {
  console.log(8)
})
//
2
5
6
8
7
3
1
4

题目8 ❌

// 宏任务队列 1
setTimeout(() => {
  // 宏任务队列 2.1
  console.log('timer_1')
  setTimeout(() => {
    // 宏任务队列 3
    console.log('timer_3')
  }, 0)
  new Promise(resolve => {
    resolve()
    console.log('new promise')
  }).then(() => {
    // 微任务队列 1
    console.log('promise then')
  })
}, 0)

setTimeout(() => {
  // 宏任务队列 2.2
  console.log('timer_2')
}, 0)
console.log('========== Sync queue ==========')
//
========== Sync queue ==========
timer_1
new promise
promise then
timer_2
timer_3

疑问:宏定时器2比定时器3先输出

题目9:

 
   async function async1() {
       console.log('async1 start');
       await async2();
       console.log('async1 end');
   }
   async function async2() {
       console.log('async2');
   }
   
   console.log('script start');
   
   setTimeout(function() {
       console.log('setTimeout');
   }, 0)
   
   async1();
   
   new Promise(function(resolve) {
       console.log('promise1');
       resolve();
   }).then(function() {
       console.log('promise2');
   });
   console.log('script end');
//
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

题目10 ❌

console.log('1')

setTimeout(function () {
  console.log('2')
  process.nextTick(function () {
    console.log('3')
  })
  new Promise(function (resolve) {
    console.log('4')
    resolve()
  }).then(function () {
    console.log('5')
  })
})
process.nextTick(function () {
  console.log('6')
})
new Promise(function (resolve) {
  console.log('7')
  resolve()
}).then(function () {
  console.log('8')
})

setTimeout(function () {
  console.log('9')
  process.nextTick(function () {
    console.log('10')
  })
  new Promise(function (resolve) {
    console.log('11')
    resolve()
  }).then(function () {
    console.log('12')
  })
})
//结果
1
7
6
8
2
4
3
5
9
11
10
12

process.nexTick在不同浏览器执行标准不一样

题目10

在这里插入图片描述

总结

  • 宏任务里如果有宏任务,不会执行里面的那个宏任务,而是被丢进任务队列后面,所以会最后执行。
  • 一个宏任务执行完才会去执行另外一个宏任务
  • async函数返回值是promise对象

题目11

console.log(1);

setTimeout(() => console.log(2));

Promise.resolve().then(() => console.log(3));

Promise.resolve().then(() => setTimeout(() => console.log(4)));

Promise.resolve().then(() => console.log(5));

setTimeout(() => console.log(6));

console.log(7);
//
1
7
3
5
2
6
4

其他题目

其他题目

总结

  • 宏任务里如果有宏任务,不会执行里面的那个宏任务,而是被丢进任务队列后面,所以会最后执行。
  • 一个宏任务执行完才会去执行另外一个宏任务
  • async函数返回值是promise对象,await后面的代码是异步微任务

立超老师

博客:

// function func() {
//   return new Promise(resolve => resolve(10))
// }
// 等价于
async function func() {
  return 10
}
func().then(console.log)
// func().then(console.log)
// func().then(num=>console.log(num)) //10

  • async声明的异步函数,它的返回值会自动包装成promise
  • async声明的异步函数中可以使用await来调用其他异步函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值