🤍 前端开发工程师、技术日更博主、已过CET6
🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1
🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》
🍚 蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》
💬 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
文章目录
JavaScript 的消息队列和事件循环是其实现异步编程和并发操作的核心机制。通过理解它们之间的关系,可以更好地理解 JavaScript 如何处理并发任务和异步操作。以下是关于 JavaScript 消息队列和事件循环的详细介绍。
1. 事件循环(Event Loop)
事件循环是一种处理异步代码的机制,它使得 JavaScript 能够在单线程环境中执行异步操作。由于 JavaScript 是单线程的,这意味着它一次只能执行一个任务,事件循环的存在使得 JavaScript 能够在不阻塞主线程的情况下处理多个任务。
1.1 运行时环境
JavaScript 运行在一个“事件循环”的环境中,其中主要包含以下几个部分:
- 执行栈(Call Stack):用于管理函数调用。执行栈是一个后进先出(LIFO)的数据结构,所有的同步代码都会在这里执行。
- 消息队列(Message Queue):存放待处理的异步任务的队列。在异步操作完成时,相应的回调函数会被放入消息队列中等待执行。
- Web APIs:浏览器提供的 APIs(如
setTimeout
、DOM
事件等),用于处理异步操作。
1.2 操作过程
事件循环的主要工作流程如下:
- 执行栈清空:事件循环会不断检查执行栈是否为空。
- 处理消息队列:如果执行栈为空,事件循环会从消息队列中取出第一个消息(即相应的回调函数)并将其放入执行栈中进行执行。
- 重复过程:重复执行以上步骤,直到没有更多的任务或消息需要处理。
2. 消息队列(Message Queue)
消息队列是一个用于存放待处理事件和异步操作回调的简单数据结构。所有的异步操作(如定时器事件、网络请求等)的回调函数都会被放入消息队列中,待事件循环去处理。
2.1 消息队列的特点
- 先进先出(FIFO):消息队列遵循先进先出原则,最早被添加的消息最早被处理。
- 异步处理:所有放入消息队列的消息的处理都是异步的,事件循环确保它们在主线程闲置时被执行。
2.2 常见的异步操作
在 JavaScript 中,常见的会将回调函数放入消息队列的异步操作包括:
- 定时器:使用
setTimeout
和setInterval
。 - 事件回调:如 DOM 事件,比如按钮点击、输入框变化等。
- 网络请求:如
fetch
、XMLHttpRequest
等。
3. 示例
下面是一个简单的示例,说明 JavaScript 如何通过事件循环和消息队列处理异步操作。
console.log("Start");
setTimeout(function() {
console.log("Timeout 1");
}, 0);
setTimeout(function() {
console.log("Timeout 2");
}, 0);
Promise.resolve().then(function() {
console.log("Promise 1");
}).then(function() {
console.log("Promise 2");
});
console.log("End");
3.1 输出顺序
- “Start” 是同步代码,立即输出。
- “End” 是同步代码,立即输出。
- 在这个时候,执行栈为空,事件循环会检查消息队列。
- Promise 的回调首先会被放入微任务(Microtask)队列中。在 JavaScript 中,微任务的优先级高于宏任务,因此“Promise 1” 和 “Promise 2” 会被优先执行。
- 接着执行消息队列中的任务,输出 “Timeout 1”和“Timeout 2”。
因此,最终输出的顺序为:
Start
End
Promise 1
Promise 2
Timeout 1
Timeout 2
4. 微任务和宏任务
在 JavaScript 的事件循环中,任务可以分为两种类型:宏任务(Macrotasks)和微任务(Microtasks)。
4.1 宏任务(Macrotasks)
宏任务通常包括:
- 常规的
setTimeout
、setInterval
- I/O 操作,事件处理等
4.2 微任务(Microtasks)
微任务的优先级高于宏任务,通常包括:
Promise
的then
、catch
、finally
等回调MutationObserver
在事件循环中,事件循环会执行完当前的任务栈后,会先处理所有的微任务,然后再处理消息队列中的宏任务。
5. 总结
JavaScript 通过事件循环和消息队列实现了异步编程的能力,允许在单线程环境中有效处理多个操作。理解事件循环和消息队列的机制,对于写出高效的 JavaScript 代码、处理复杂的异步流程至关重要。通过合理使用这些机制,可以提高程序的响应速度和用户体验。