宏任务和微任务

252 阅读2分钟

宏任务和微任务的概念介绍

概念

js 是单线程的,也就代表 js 只能一件事情一件事情执行,那如果一件事情执行时间太久,后面要执行的就需要等待,需要等前面的事情执行完成,后面的才会执行。

所以为了解决这个问题,js 委托宿主环境(浏览器)帮忙执行耗时的任务,执行完成后,在通知 js 去执行回调函数,而宿主环境帮我们执行的这些耗时任务也就是异步任务

js 本身是无法发起异步的,但是 es5 之后提出了 Promise 可以进行异步操作

执行流程

1.主线程先判断任务类型

  1. 如果是同步任务,主线程自己执行
  2. 如果是异步任务,交给宿主环境(浏览器)执行

2.浏览器进行异步任务的执行,每个异步执行完后,会将回调放进任务队列,先执行完成的先放进任务队列,依次放入

3.等主线程任务全部执行完后,发现主线程没有任务可执行了,会取任务队列中的任务,由于任务队列里是依次放入进来的,所以取得时候也会先取先进来的,也就是先进先出原则

4.在任务队列中取出来的任务执行完后,在取下一个,依次重复,这个过程也称为 eventLoop 事件轮训

宏任务

异步任务分为宏任务和微任务

由宿主环境发起的异步任务:宏任务

settimeOut、setinterval、特殊的(代码块、script)

微任务

由 javascript 自身发起的异步:微任务

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

1.先执行宏任务

2.宏任务执行完后看微任务队列是否有微任务

3.没有微任务执行下一个宏任务

4.执行完微任务,执行下一个宏任务

案列1

console.log(1)

setTimeout(function() {

console.log(2)

}, 0)

new Promise(function(resolve) {

console.log(3)

resolve()

}).then(function() {

console.log(4)

})

console.log(5) // 1 3 5 4 2

案列2

注意点:await 的执行顺序为从右到左,会阻塞后面的代码执行,但并不是直接阻塞 await 的表达式

await 下面(下面不是右面)的代码可以理解为 promise.then(function(){ 回调执行的 })

async function async1() {

console.log('async1 start')

await async2()

// await后面的代码可以理解为promise.then(function(){ 回调执行的 })

console.log('async1 end')

}

async function async2() {

console.log('async2')

}

console.log('script start')

setTimeout(function() {

console.log('setTimeout')

}, 0)

async1()

console.log('script end') // script start、async1 start、async2、script end、async1 end、setTimeout

案列3

console.log(1)

setTimeout(function() {

console.log(2)

}, 2000)

new Promise(function(resolve) {

console.log(3)

resolve()

}).then(function() {

console.log(4)

})

setTimeout(function() {

console.log(5)

new Promise(function(resolve) {

console.log(6)

resolve()

}).then(function() {

console.log(7)

})

}, 3000)

setTimeout(function() {

console.log(8)

new Promise(function(resolve) {

console.log(9)

resolve()

}).then(function() {

console.log(10)

})

}, 1000) // 1、3、4、8、9、10、2、5、6、7