我们今天来聊聊 JavaScript 事件循环。虽然这个词听起来很高深,但你可以把它想象成一个奶茶店里排队买奶茶的过程。主线程就像奶茶店的唯一一个店员,任务就是那些排队的订单,而 JavaScript 的事件循环就是这个店员处理订单的工作方式。
先看代码,咱们慢慢聊:
console.log('1: 进店点单(同步任务)'); // 主线程同步任务
setTimeout(() => {
console.log('2: 奶茶做好了!(宏任务:setTimeout)'); // 异步宏任务
}, 0);
Promise.resolve().then(() => {
console.log('3: 加料(微任务:Promise.then)'); // 异步微任务
});
console.log('4: 等奶茶期间,看个短视频(同步任务)'); // 主线程同步任务
执行结果:
1: 进店点单(同步任务)
4: 等奶茶期间,看个短视频(同步任务)
3: 加料(微任务:Promise.then)
2: 奶茶做好了!(宏任务:setTimeout)
事件循环 = 一杯奶茶 + 主线程
JavaScript 是单线程的,意思是奶茶店只有一个店员。这个店员一次只能处理一个任务,也就是“同步任务”。如果有异步任务(比如做奶茶需要时间),店员会先继续做其他简单的事情,等到奶茶做好了再回来处理异步任务。
看上面的例子:
-
第1步和第4步:这些都是同步任务,类似于你进店点单和等待时刷短视频。这些任务是直接执行的,不需要等。
-
第2步:
setTimeout
是异步的宏任务,类似于奶茶需要煮好珍珠再给你。这个任务会被放到宏任务队列里,等到同步任务完成后再执行。 -
第3步:
Promise.then
是微任务,类似于“加料”。微任务虽然是异步的,但它很重要,总是插队在宏任务前面执行。比如珍珠已经煮好了,但你先让店员加点其他料,这个加料就相当于微任务的执行。
宏任务 vs 微任务:点单和加料的小争斗
-
宏任务(Macro Task):像
setTimeout
这样的任务,会被放到“宏任务队列”里。它们类似于做一杯完整奶茶的主要步骤。等主线程上的同步任务全部完成后,才会去处理这些宏任务。 -
微任务(Micro Task):比如
Promise.then
这样的微任务,虽然也是异步的,但它总会优先于宏任务执行。你可以想象,微任务就像奶茶的“小料”,不做完就没法给你奶茶。
事件循环的秘密:一切尽在秩序中
当你执行一段 JavaScript 代码时,事情是这样安排的:
- 主线程先执行同步任务:像点奶茶这种同步任务,直接执行。
- 微任务插队:如果有微任务,比如加料,它们会在同步任务完成后,宏任务开始前执行。
- 宏任务靠后排:宏任务会在所有同步和微任务完成后执行。
在代码示例中:
console.log('1: 进店点单')
和console.log('4: 看短视频')
是同步任务,直接按顺序执行。Promise.then
(微任务)在同步任务后执行,但比setTimeout
(宏任务)优先。setTimeout
(宏任务)在所有同步和微任务完成后执行。
总结:程序员的"点单"时刻
JavaScript 主线程就像一位疲惫的店员,面对大量订单和复杂要求,但它从不慌乱。它会根据优先级处理所有任务,让我们像喝奶茶一样丝滑流畅地体验页面。
“我点了奶茶,为什么是珍珠先到了?” —— 微任务笑着说:“因为我插队啦!”
这就是事件循环的魅力所在,虽然任务纷繁复杂,但总有一个清晰的执行顺序。掌握了这个顺序,JavaScript 的世界就像奶茶一样甜美可口!
标签:执行,同步,JavaScript,任务,奶茶,搞懂,setTimeout,程都 From: https://blog.csdn.net/qq_44996048/article/details/142988064