事件循环(Event Loop)

一、什么是Event Loop🤔

JavaScript是一门单线程语言,它一个时间只能做一件事;

在js代码运行的时候,会形成一个执行栈,每调用一个函数,就会把该函数的执行上下文放入执行栈;

另外还有任务队列存放待完成的任务,在js中,有同步任务异步任务 ,异步任务又分为宏任务微任务

因为script代码整体就是一个宏任务,因此事件循环先从一个宏任务开始,当执行完宏任务后,就从微任务队列拿微任务到执行栈中执行,当前微任务队列所有微任务执行完后,就执行宏任务队列的下一个宏任务;

然后重复这个操作,直到任务队列里的任务执行完,这个过程就叫事件循环。

二、宏任务和微任务📜

JavaScript 的事件分两种,宏任务 (macro-task)和微任务(micro-task)。

1. 宏任务

  • script
  • setTimeout
  • setInterval
  • setImmediate

2. 微任务

  • promise.then() promise.catch() 的回调cb
  • async await
  • mutationObserver ==> 监听DOM的改变
  • process.nextTick() ==> Node

关系: 微任务是包含在宏任务里面的,一个宏任务中,可以有多个微任务。

3. 执行顺序

  • 首先script代码块可以看做第一个宏任务,开始第一个Tick事件循环
  • 会先执行script代码块中的同步代码
  • 如果遇到宏任务,就放到宏任务队列中等待执行, 如果遇到微任务,放到微任务队列中
  • 当主线程执行完同步代码的时候,首先去微任务队列中清空当前事件循环的所有微任务(本轮事件循环Tick结束)
  • 如果还有异步的宏任务,那么就会进行循环执行上述的操作

三、来点例子🌰

eg1:

js 复制代码
const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve(5);
    console.log(2);
}).then(val => {
    console.log(val);
});

promise.then(() => {
    console.log(3);
});

console.log(4);

setTimeout(function() {
    console.log(6);
});

// 1  2  4  5  3  6

执行结果为: 1 2 4 5 3 6

eg2:

js 复制代码
async function async1() {
    console.log('async1 start')  
    await async2()      // await这一行,这个async2 同步执行的; await的下面,放到微任务队列
    console.log('async1 end') // 这一行,相当于放到.then()中  微1 
    console.log(666)
}
async function async2() {
    console.log('async2')
}

console.log('script start')  

setTimeout(function() {
    console.log('setTimeout') // 放到宏任务队列中 宏1 
}, 0)

async1();

new Promise(function(resolve) {
    console.log('promise1')
    resolve();
}).then(function() {
    console.log('promise2')  // 微任务  微2 
});
console.log('script end')

// script start 
// async1 start
// async2
// promise1
// script end
// async1 end
// 666
// promise2  (本轮tick结束)
// setTimeout

执行结果为:

✨✨✨✨✨✨✨✨✨✨

在本轮事件循环中的微任务比下一次的事件循环中的宏任务优先级高,也就是我们要将这轮的微任务都执行完毕,才能去执行下一个宏任务。

相关推荐
To_OC7 小时前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC7 小时前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
天渺工作室8 小时前
实现一个adblock/adblock plus等浏览器广告拦截器检测插件
前端·javascript
kyriewen16 小时前
2026 年了,还在用 Node.js?Bun 迁移实战:20 分钟搞定,附踩坑记录
前端·javascript·node.js
minglie21 小时前
一个置换问题
javascript
默_笙1 天前
🌀 别再手动写 Prompt 了!我让 AI 自己循环改到满意为止
javascript
To_OC1 天前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
To_OC2 天前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode
labixiong2 天前
实现一个能跑的迷你版Promise(一)
前端·javascript·面试
weedsfly2 天前
还在用 Axios?你可能需要重新理解 XHR 与 Fetch
前端·javascript·面试