JS -- 宏任务与微任务

512 阅读2分钟

浏览器是多线程的。 JS是单线程:浏览器只给了其中一个进程来渲染,但浏览器又提供了事件队列(Event Queue)来处理异步任务。事件队列中又包括了微任务与宏任务。浏览器会先执行微任务,再执行宏任务。

宏任务
  • 定时器
  • 事件绑定
  • ajax
微任务
  • async
  • awiat
  • promise中的resolve() / reject()
同步任务
  • new promise
async function async1() {
  console.log('async1 start')
  await async2()  // await后面的代码会放入微任务队列中
  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
//3 7 4 1 2 5 
const first = () => (new Promise((resolve, reject) => {
  console.log(3)
  let p = new Promise((resolve, reject) => {
    console.log(7)
    setTimeout(() => {
      console.log(5)
      resolve(6) //会被忽略,因为会先执行微队列里的resolve(1),此时状态已经改变过了,且状态只能改变一次
    }, 0)
    resolve(1)
  })
  resolve(2)
  p.then((arg) => {
    console.log(arg)
  })
}))

first().then((arg) => {
  console.log(arg)
})
console.log(4)
// 1, 7, 2, 3,8,4, 6, 5, 0
setTimeout(() => {
  console.log("0")
}, 0)
new Promise((resolve, reject) => {
  console.log("1")
  resolve()
}).then(() => {
  console.log("2")
  new Promise((resolve, reject) => {
    console.log("3")
    resolve()
  }).then(() => {
    console.log("4")
  }).then(() => {
    console.log("5")
  })
}).then(() => {
  console.log("6")
})

new Promise((resolve, reject) => {
  console.log("7")
  resolve()
}).then(() => {
  console.log("8")
})
async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end')
}
async function async2() {
    console.log('async2 start')
    return new Promise((resolve, reject) => {
        resolve()
        console.log('async2 promise')
    })
}
console.log('script start')
setTimeout(function () {
    console.log('setTimeout')
}, 0)
async1()
new Promise(function (resolve) {
    console.log('promise1')
    resolve()
}).then(function () {
    console.log('promise2')
}).then(function () {
    console.log('promise3')
})
// script start, async1 start, async2 start, async2 promise, promise1
// promise2, promise3, async1 end?
// setTimeout

2022.10,17补充

  • 调用栈:后进先出。放的是要执行的代码。
  • 定时器:间隔一段时间后,将函数放入到任务队列
  • Promise在执行,then就相当于给Promise了回调函数。当Promise的状态从pending变为fulfilled时,then的回调函数就会被放入任务队列
  • 任务队列分为两种:
    • 宏任务队列:
    • 微任务队列:Promise的回调函数(then、catch、finally)。queueMicrotash()用来向微任务队列中添加一个任务。
  • 执行流程
      1. 先执行调用栈的所有
      1. 中兴所有的微任务队列
      1. 执行宏任务队列