Event Loop
调用栈,后入先出
JS 中的任务
任务没有优先级,在消息队列中先进先出
同步任务(渲染主线程)
- 解析 HTML
- 解析 CSS
- 样式计算
- 处理图层
- 页面渲染刷新 60/Hz
- 执行全局 JS 代码
- 执行事件
- 执行定时器回调函数
- ...
微任务(Microtasks,由 JS 引擎发起)
Promise.then().catch()
(Promise
是同步的,.then
或者.catch
才是异步)Async / Await
process.nextTick()
MutationObserver
Object.observe()
已废弃
宏任务(Macrotasks,由宿主环境发起(如浏览器、Node))
script
(标签代码块)- 事件(如
addEventListener
) - 网络请求(
ajax、fetch
) setTimeout()、setIntever()
执行栈
问题
1. 什么是事件循环?
JS
引擎是单线程的,为了防止代码阻塞,浏览器将代码分为了同步任务与异步任务;- 同步任务的代码会被
JS
引擎立即执行,并放入到执行栈中,异步代码将会在触发后(如用户点击事件,setTimeout
回调等)被放入宿主环境的任务队列中(队列,先进先出); - 执行栈中的任务执行完毕后,会去任务队列中查看是否存异步任务,存在则将其放入执行栈中执行;
- 这种反复从任务队列中查看异步任务并执行的过程,就是事件循环。
2. 什么是宏任务与微任务?
最新标准:因为浏览器的复杂度提升,W3C已不再使用宏任务队列说法,而是根据任务类型拆分为多种队列
chrome
的当前实现入下:
队列名称 | 优先级 | 说明 |
---|---|---|
微队列 | 最高 | 原有的微任务队列 |
交互队列 | 高 | 存放用户操作事件 |
延时队列 | 较高 | 存放定时器回调任务 |
3. 代码题
JS
new Promise(resolve => {
resolve(1)
new Promise(resolve => {
resolve(2)
}).then(res => {
console.log(res)
})
}).then(res => {
console.log(res)
})
console.log(3)
new Promise(resolve => {
resolve(1)
new Promise(resolve => {
resolve(2)
}).then(res => {
console.log(res)
})
}).then(res => {
console.log(res)
})
console.log(3)
答案: 3 2 1
4. 代码题
JS
console.log(1)
setTimeout(() => {
console.log(2)
new Promise(resolve => {
resolve(3)
}).then(res => {
console.log(res)
})
console.log(4)
}, 0)
console.log(5)
console.log(1)
setTimeout(() => {
console.log(2)
new Promise(resolve => {
resolve(3)
}).then(res => {
console.log(res)
})
console.log(4)
}, 0)
console.log(5)
答案:1 5 2 4 3
5. 代码题
JS
setTimeout(() => {
console.log(1)
}, 0)
new Promise(resolve => {
console.log(2)
resolve(3)
new Promise(resolve => {
console.log(4)
setTimeout(() => {
console.log(5)
}, 0)
resolve(6)
}).then(res => {
console.log(res)
})
setTimeout(() => {
console.log(7)
}, 0)
}).then(res => {
console.log(res)
})
console.log(8)
setTimeout(() => {
console.log(1)
}, 0)
new Promise(resolve => {
console.log(2)
resolve(3)
new Promise(resolve => {
console.log(4)
setTimeout(() => {
console.log(5)
}, 0)
resolve(6)
}).then(res => {
console.log(res)
})
setTimeout(() => {
console.log(7)
}, 0)
}).then(res => {
console.log(res)
})
console.log(8)
答案:2 4 8 6 3 1 5 7