网上查了很多JS事件循环机制,没有一个总结,很对人对具体的概念有比较模糊。
所以今天深入理解一下JS事件循环机制到底是什么东西
概念
事件机制的三个主要组成部分
- 调用栈:用于存储主线程中代码的执行顺序。
- 任务队列:用于存储异步任务(如定时器,事件监听等)的回调函数
- 事件循环线程:负责循环监听队列中是否有任务需要执行。如果有,则将任务添加到调用栈中执行。
当代码遇到一个异步任务时,会将该任务的回调函数添加到任务队列中。当调用栈中的代码执行完成后,事件循环线程会从任务队列中取出一个任务添加到调用栈中执行。这个任务过程是一直重复的,直到任务队列中没有任何的任务为止。需要注意的是,任务队列中的任务被执行的顺序有先进先出的原则。
JS异步请求
js是一门单线程的语言,是通过事件循环机制实现单线程的。在设计初期,由于JS是运行在浏览器端的脚本语言,目的就是为了实现与页面的动态交互,其核心就是DOM操作,这就决定了他必须使用单线程去处理脚本信息,从而避免对同一DOM元素同时进行操作时产生冲突问题。
异步任务
异步任务分为宏任务(macrotask)与微任务(microtask)。
- 宏任务(task):就是js内部(任务队列里)的任务,严格按照时间顺序执行。如setTimeout,setInverter,setImmediate,MessageChannel等。
- 微任务:通常来说就是需要在当前任务执行结束后立即执行的任务,例如需要对一系列的任务做出回应,或者是需要异步的执行任务而又不需要分配的一个新的任务,这样便可以减小一点性能的开销。
在代码中的执行顺序,同步任务>微任务>宏任务
仅通过上面的文字可能不容易理解,写几段代码就懂了
console.log(1)
setTimeout(() => {
console.log(4)
}, 0);
new Promise(resolve=>{
console.log(5)
resolve(3)
}).then(res=>{
console.log(res)
})
console.log(2)
答案:15234。同步任务:152,微任务:3,宏任务:4。这里只有一个需要注意的地方就是Promise,.then方法才是微任务,console.log(5)是同步任务。
console.log(1);
setTimeout(() => {
console.log(4);
}, 0);
new Promise((resolve) => {
console.log(5);
resolve(3);
new Promise((resolve) => {
console.log(6);
resolve(7);
}).then((res) => {
console.log(res);
});
}).then((res) => {
console.log(res);
});
console.log(2);
答案:1562734 同步任务:1562 微任务:73 宏任务:4 这里需要注意的地方是Promise.then()这个微任务放到事件队列的顺序,并不是执行到resolve()方法就会将这个微任务加入到事件队列,而是要执行到.then方法的才会被加入事件队列,所以6在前而7在后(ps:事件队列可以理解为要被执行的微任务会被加入到事件队列,先进先出)