JavaScript中的事件循环&宏任务和微任务
JavaScript事件循环
JavaScript中的事件循环(Event Loop)是一种用于处理异步操作的机制。它是JavaScript运行时环境的一部分,用于管理和调度事件、回调函数和其他任务的执行顺序。
事件循环的核心思想是将异步任务分为不同的阶段,并按照特定的顺序执行它们。这种机制确保了JavaScript的单线程执行模型,同时允许处理大量的异步操作。
事件循环的基本流程
执行栈 => 挂起任务 => 事件队列 => 执行栈
- JS语言是单线程非阻塞语言,单线程也就是说只有一个主线程来控制代码的执行。
- 当JS代码第一次执行时,js引擎会去解析代码,把代码放入到执行栈中,然后从头开始执行代码,如果要执行函数,会在执行栈当中创建函数的执行上下文,函数执行完毕后,会销毁这个执行上下文,这些都是同步执行的代码。
- 如果有异步的代码,比如ajax请求,请求事件执行完以后,主线程并不会等待回调函数的执行结果,而是将这个事件挂起,继续执行栈中的其他任务。当异步事件返回结果,js会将这个事件加入到和执行栈不同的另一个队列,事件队列。被放入事件队列的事件不会立即执行,而是在执行栈中所有的任务执行完毕,主线程处于空闲状态时,主线程回去查找事件队列是否有任务。如果有任务,主线程会把事件队列的事件放入执行栈中,执行其同步任务。
- 这样反复执行,就形成一个循环。这个过程被称为“事件循环(Event Loop)”。
宏任务 、微任务
异步任务和异步任务之间也是不相同的,他们执行的优先级也是有区别的,不同的异步任务被分为两类,微任务 和 宏任务。
可以理解成事件队列是有2个,一个宏任务队列,一个是微任务队列。主线程空闲时,会去先查看微任务队列是否有事件,如果没有或者微任务队列里面的事件执行完,就去查看宏任务队列。
所以,当当前执行栈执行完毕时,会立刻先处理所有微任务事件队列中的事件,然后再去宏任务队列取事件,同一次事件循环中,微任务永远在宏任务之前执行。
宏任务:
setTimeout()
setInterval()
微任务:
new Promise().then().resolve()
new MutaionOvserver()
下面代码可以验证 2 1 3
setTimeout(function () {
console.log(1);
});
new Promise(function(resolve,reject){
console.log(2)
resolve(3)
}).then(function(val){
console.log(val);
})
new MutationObserver() 的使用,和 setTimeout和MutationObserver的先后顺序结果是 2 1
let oDiv = document.getElementById('box');
let config = {
attributes: true,
childList: true,
subtree: true
}
let observer = new MutationObserver(function(mutationsList, observer) {
// console.log(mutationsList, observer);
console.log(2)
})
observer.observe(oDiv, config);
let oBtn = document.getElementById('btn');
setTimeout(() => {
console.log('1') ;
})
oDiv.className = "asdf"