一、event loop机制
js是单线程的,异步任务和dom事件都是基于event loop实现的。
二、event loop机制
1、同步代码一行一行(script整体代码)放入call stack(调用栈)中执行
2、遇到异步代码(setTimeout和ajax请求等),浏览器先记录下来,等待时机将回调函数放入callback queue(回调队列)中。
3、当call stack空闲时,event loop机制启动
4、轮询查找callback queue有无回调函数,如有则移动到call stack中执行
三、异步代码的分类与区别
1、宏任务和微任务的规范
宏任务由浏览器宿主提供,如script(整体代码块)、setTimeout、setInterval、Dom事件、ajax请求(浏览器分配给js引擎的)。
微任务由es6规定的语法提供,如promise.then和async/await(js引擎自己发起的)。
2、宏任务和微任务的区别
(1)执行顺序不一样
当call stack空闲时,浏览器会尝试dom渲染(如果dom结构发生变化),此过程在event loop启动前执行。
微任务会在dom渲染前触发,而宏任务在dom渲染后触发。
(2)为什么微任务优先级高于宏任务?
es6为高优先级的任务提供一个优先执行的机会?
四、微任务和宏任务、dom渲染、event loop过程
js执行与dom渲染公用同一线程。
1、同步代码一行一行(script整体代码)放入call stack执行
2、当call stack空闲时,会触发micro task queue中的微任务回调函数
3、尝试dom渲染
4、启动event loop机制,查询callback queue将callback queue中的宏任务移动到call stack中执行
5、以此往复
五、经典面试题
涵盖了 宏任务(script代码块、setTimeout)、微任务(promise的excutor和then方法、async/await)执行过程的问题
async function async1 () {
console.log('async1 start')
await async2() // 这一句会同步执行,返回 Promise ,其中的 `console.log('async2')` 也会同步执行
console.log('async1 end') // 上面有 await ,下面就变成了“异步”,类似 cakkback 的功能(微任务)
}
async function async2 () {
console.log('async2')
}
console.log('script start')
setTimeout(function () { // 异步,宏任务
console.log('setTimeout')
}, 0)
async1()
new Promise (function (resolve) { // 返回 Promise 之后,即同步执行完成,then 是异步代码
console.log('promise1') // Promise 的函数体会立刻执行
resolve()
}).then (function () { // 异步,微任务
console.log('promise2')
})
console.log('script end')