浏览器事件循环
- 进程: 计算机分配和调度任务的最小单位;
- 浏览器是一个多进程模型,每个页卡都是一个独立的进程(稳定)
- 每个浏览器进程含有哪些线程:(主线程是单线程的)
- GUI渲染线程 页面渲染、绘图、3d动画
- js渲染引擎 执行js代码,当js执行时,渲染线程会挂起 -> 渲染时不能执行js
- 事件触发线程 EventLoop
- webApi也会创建线程 事件、定时器、ajax…
- webworker
宏任务 微任务
-
宏任务 script标签、UI渲染、setTimeout、setInterval、setImmediate(IE)、ajax、DOM事件、MessageChannel(消息通道)、(node中:I/O操作、) -
微任务 promise、MutationObserverer、queueMicrotask、Object.observe(node中:process.nextTick) -
requestAnimationFrame 渲染之前执行 (浏览器大约每16.6ms执行一次,也有可能不渲染) -
requestIdleCallback 空闲时间执行
- 事件循环
首先执行(一个)宏任务,再清空所有微任务,再执行页面渲染(有可能不渲染,渲染前会执行requestFrameAnimation,渲染后会执行requestIdleCallback),此时一个事件循环结束;然后等待ajax、定时器等宏任务执行完毕,将回调函数放入宏任务队列,然后开启下一轮事件循环
- 如果微任务中产生微任务,会将产生的微任务放到微任务队列中继续执行(清空操作)
- 事件循环不停地扫描是否有宏任务过来
- 每次执行宏任务,都会创造一个新的微任务队列,宏任务队列只有一个
document.body.style.background = 'red';
Promise.resolve().then(() => {
document.body.style.background = 'yellow'
})
document.body.style.background = 'red';
setTimeout(() => {
document.body.style.background = 'yellow'
},0)
button.addEventListener('click', () => {
console.log('listener1')
Promise.resolve().then( () => { console.log('micro task1') } )
})
button.addEventListener('click', () => {
console.log('listener2')
Promise.resolve().then( () => { console.log('micro task2') } )
})
- await连接的语句是同步执行的,之后的代码是异步执行的
console.log(1);
async function async() {
console.log(2);
await console.log(3);
console.log(4)
}
setTimeout(() => {
console.log(5);
}, 0);
const promise = new Promise((resolve, reject) => {
console.log(6);
resolve(7)
})
promise.then(res => {
console.log(res)
})
async();
console.log(8)
Promise.resolve().then(() => {
console.log(0)
return Promise.resolve(4)
}).then(res => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1)
}).then(() => {
console.log(2)
}).then(() => {
console.log(3)
}).then(() => {
console.log(5)
})
|