说明
ES6之后引入了Promise对象,让js引擎也可以发起异步任务。
异步任务分为:
- 宏任务:由浏览器环境执行和管理的异步代码
- 微任务:由JS引擎环境执行的异步代码,由js引擎发起和管理
下面这些是宏任务:
任务(代码) | 执行所在环境 |
---|---|
js脚本执行事件(script标签) | 浏览器 |
setTimeout/setInterval | 浏览器 |
ajax请求完成事件 | 浏览器 |
用户交互事件等 (如点击事件、鼠标滚轮事件) | 浏览器 |
下面这些是微任务:
任务(代码) | 执行所在环境 |
---|---|
Promise对象.then() | js引擎 |
备注:new Promise对象本身是同步的,而then和catch中的回调函数是异步的。
事件循环模型将任务队列拆分成了宏任务队列和微任务队列:
当调用栈空闲的时候,会优先调用微任务队列中的任务,因为微任务队列更接近js引擎。
javascript内代码如何执行?
- 执行第一个script脚本事件宏任务,执行script标签里面的同步代码
- 遇到宏任务交给浏览器宿主环境执行,微任务交给js引擎执行。宏任务中的回调函数进入宏任务队列,微任务中的回调函数进入微任务队列
- 同步代码执行完成后,调用栈空闲了,优先清空微任务队列中的回调,然后是宏任务队列中的回调
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>微任务与宏任务</title>
</head>
<body>
<script> // script标签事件属于宏任务
console.log(1) // 同步
setTimeout(() => {
console.log(2) // 宏任务
}, 0)
const p = new Promise((resolve, reject) => {
console.log(3) // 同步代码
resolve(4) // 同步代码
})
p.then(res => {
console.log(res) // 微任务
})
console.log(5) // 同步代码
</script>
</body>
</html>