一个 事件循环-宏任务-微任务 的例子

发布于:2024-10-18 ⋅ 阅读:(10) ⋅ 点赞:(0)

JavaScript 中,任务分为 同步任务异步任务,异步任务分为 宏任务微任务

在 ES6 中,JavaScript 引入 Promise ,至此,不需要浏览器,JavaScript 引擎也可以发起异步任务了。

宏任务 是由宿主(浏览器,Node)发起的,微任务 是由 JavaScript 引擎发起的。

代码可能有三种:

  1. 同步代码(JavaScript执行栈/回调栈)
  2. 微任务的异步代码(JavaScript引擎)
    • process.nextTick (node)
    • Promise.then() catch() (注意,Promise本身是同步的,但是then和catch的回调是异步的)
    • async 和 await
    • Object.observe 等等
  3. 宏任务的异步代码(宿主环境)
    • script(代码块)
    • setTimeout/setInterval 定时器
    • setImmediate 定时器

执行顺序

执行顺序是:

  1. 同步代码
  2. 微任务的异步代码(Promise等)
  3. 宏任务的异步代码(setTimeout,setInterval等)

首先执行 执行栈 中的同步代码,执行完毕后,如果 微任务队列 中有待执行的微任务,则通过 事件循环微任务队列 中的 微任务 推入 执行栈 中并执行,执行完毕后,如果 宏任务队列 中有待执行的任务,则将其推入 执行栈 并执行。

console.log(1) // 代码段1

setTimeout(function () { // 代码段2
	console.log(2)
},0)

const p = new Promise((resolve,reject) => { // 代码段3
	console.log(3) // 代码段3.1
	resolve(1000) // 代码段3.2
	console.log(4) // 代码段3.3
})

p.then(data => { // 代码段4
	console.log(data)
}

console.log(5) // 代码段5

分析:
代码段1 是同步任务,推入执行栈。
代码段2 是宏任务,放入宏任务队列。
代码段3 new Promise 是同步执行的,所以 代码段3.1 推入执行栈,代码段3.2仅标志状态为成功,不执行操作,代码段3.3 推入执行栈。
代码段4 代码段3.2 已将 p 标志为成功,会异步地调用 then ,所以 代码段4 放入微任务队列。
代码段5 推入执行栈。

目前执行栈中有:代码段1,代码段3.1,代码段3.3,代码段5;微任务队列中有:代码段4;宏任务队列中有:代码段2

按照顺序执行,打印顺序是
1,3,4,5,1000,2