深入理解JavaScript的事件循环机制
myzbx 2025-01-10 15:41 20 浏览
导语:
JavaScript 作为一门单线程语言,却能高效处理各种异步操作,这背后离不开其独特的事件循环(Event Loop)机制。理解事件循环,不仅能让你更好地驾驭 JavaScript,还能帮你避免常见的异步陷阱。如果你对 JavaScript 的异步行为感到困惑,那么这篇文章将为你揭开它的神秘面纱。
正文:
1. JavaScript 是单线程的,为什么还能处理异步?
首先,我们要明确一个概念:JavaScript 引擎本身是单线程的,这意味着它一次只能执行一个任务。那为什么我们还能使用 setTimeout、fetch 等异步操作,而不阻塞主线程呢?
这是因为 JavaScript 的运行环境(比如浏览器或 Node.js)并非单线程的,它们提供了额外的能力,比如:
- Web API (浏览器): 提供了诸如 setTimeout、DOM Events、fetch 等接口。
- Node.js API (Node.js): 提供了文件 I/O、网络请求等功能。
这些 API 在遇到异步任务时,会将任务委托给其他线程(例如,浏览器内核中的线程),当异步任务完成后,再通知 JavaScript 主线程。这个过程就是事件循环的核心。
2. 什么是调用栈(Call Stack)?
调用栈就像一个堆叠的盘子,每次调用一个函数,就会把函数压入栈中,函数执行完毕后,就会从栈中弹出。JavaScript 主线程每次执行的任务都是从调用栈中拿取的。
function foo() {
console.log("foo called");
bar();
}
function bar() {
console.log("bar called");
}
foo();
在这个例子中,foo() 和 bar() 会依次被压入调用栈,bar() 执行完后弹出,然后 foo() 执行完弹出。
3. 任务队列(Task Queue)/ 回调队列(Callback Queue)
当异步任务(如 setTimeout、fetch)完成后,它们的回调函数不会立即进入调用栈,而是会被放入任务队列(也称为回调队列)。 任务队列就像一个等待执行的函数列表。
任务队列分两种:
- 宏任务队列(Macrotask Queue): 例如 setTimeout、setInterval、setImmediate (Node.js)、requestAnimationFrame (浏览器)、I/O 操作、UI rendering。
- 微任务队列(Microtask Queue): 例如 Promise.then、async/await、queueMicrotask、MutationObserver。
4. 事件循环(Event Loop)的运作方式
事件循环就是不断地监控调用栈和任务队列,它的工作方式可以用以下伪代码来描述:
while (true) {
// 1. 检查调用栈是否为空
if (callStack.isEmpty()) {
// 2. 如果调用栈为空,先检查微任务队列
if (!microtaskQueue.isEmpty()) {
// 从微任务队列中取出第一个任务并执行
const microtask = microtaskQueue.shift();
callStack.push(microtask);
// 循环执行 微任务,直到微任务队列为空
while(!microtaskQueue.isEmpty()){
const microtask = microtaskQueue.shift();
callStack.push(microtask);
}
}else{
// 3. 如果微任务队列为空,再检查宏任务队列
if (!macrotaskQueue.isEmpty()) {
// 从宏任务队列中取出第一个任务并执行
const macrotask = macrotaskQueue.shift();
callStack.push(macrotask);
}
}
}
}
简单来说,事件循环会:
- 检查调用栈: 看看调用栈是否为空。
- 优先检查微任务队列: 如果调用栈为空,则会先检查微任务队列,将队列中的所有微任务依次执行完毕,直到微任务队列为空。
- 执行宏任务队列: 然后检查宏任务队列,取出最老的宏任务到调用栈中执行。
- 重复执行: 不断循环以上步骤。
5. 代码示例:理解执行顺序
console.log('script start');
setTimeout(() => {
console.log('setTimeout 1');
Promise.resolve().then(() => {
console.log('promise inside setTimeout')
})
}, 0);
Promise.resolve().then(() => {
console.log('promise 1');
});
Promise.resolve().then(() => {
console.log('promise 2');
});
console.log('script end');
这段代码的执行顺序是:
- script start
- script end
- promise 1
- promise 2
- setTimeout 1
- promise inside setTimeout
解释:
- 首先,同步代码按顺序执行,输出 script start 和 script end。
- Promise 的 then 回调放入微任务队列。
- setTimeout 的回调放入宏任务队列。
- 当前同步代码执行完毕后,先清空微任务队列,输出 promise 1 和 promise 2。
- 然后,事件循环取出一个宏任务执行,即 setTimeout 的回调函数,输出 setTimeout 1, 之后遇到了微任务,放到微任务队列,循环检测,输出 promise inside setTimeout
- 最终,事件循环继续执行下一轮。
总结:
JavaScript 的事件循环机制是理解异步编程的关键。它通过调用栈、任务队列和事件循环之间的协作,实现了 JavaScript 的非阻塞执行。
相关推荐
- 如何用Java还原童年回忆?在线教你完成贪吃蛇小游戏
-
今天我就从零开始来完成这个小游戏,完成的方式也是一步一步的添加功能这样的方式来实现。额,不好意思,放错了,重来第一步完成的功能:写一个界面大家见到的贪吃蛇小游戏,界面肯定是少不了的。因此,第一步就是写...
- 金士顿Canvas Go!Plus microSD卡评测 4K影像轻松驾驭
-
【ZOL中关村在线原创评测】如今,视频已经成为社交媒体的主流内容传播形式,全民自媒体时代更是让昔日被视为高端、专业的视频拍摄,走进大众的生活。同时,无人机、运动相机等新世代影像设备也已经支持了4K视频...
- 国外顶尖教程大师教你设计一个炫酷游戏海报...
-
今天的教程很实用,我想对于做网页设计的童鞋肯定非常想学会用Photoshop的合成技巧来制作高端的游戏网站我们将用很多素材和照片来合成一个场景和一些页头和导航的制作。过程需要很长时间,素材也很多,我自...
- Excel 制作贪吃蛇游戏,让你轻松摸鱼!
-
步骤1:准备工作表1.创建游戏区域:o在单元格区域(如B2:AK30)设置一个矩形区域,调整行高和列宽为正方形(如行高20像素,列宽3字符)。o设置背景色为深色(如黑色),作为游戏画布。2.初...
- 成长的画布,绘满童趣色彩
-
在万家丽热闹的脉动中,特步童装是一方柔软的画布,等待孩子们用欢笑与奔跑泼洒斑斓色彩。这里没有生硬的商业气息,每一件衣物都像会呼吸的精灵,悄悄诉说着关于童年的奇妙物语。漫步其中,仿佛踏入一座流动的童话森...
- 【教育高质量发展】施甸县示范小学:地面为画布 游戏“绘”出精彩童年
-
近日,施甸县示范小学积极践行“健康第一”教育理念,在寒假前夕,学校美术组教师联合部分师生完成了校园地面游戏彩绘工作。教师们以地面为画布,绘制跳格子、转盘、迷宫等游戏图案,为下学期师生15分钟课间做好了...
- 《国王的画布》Steam试玩发布 手绘风地图制作工具
-
HannesBreuer工作室制作并发行,一款手绘风地图制作工具游戏《国王的画布》Steam试玩发布,本作暂不支持中文。《国王的画布》游戏中玩家可以自定义交互式路径生成随机元素,易于调整改动。无需...
- 怪物收集RPG冒险游戏《妖之乡》7月16日正式发售
-
今日(6月18日),怪物收集RPG冒险游戏《妖之乡》更新发售日消息,该作将于7月16日发售,游戏试玩Demo现已正式上线,感兴趣的玩家可以进入商店页面。游戏介绍:《妖之乡》是一款东方奇幻的怪物收集R...
- 208元起,育碧第一人称动作冒险游戏《阿凡达:潘多拉边境》发售
-
IT之家6月18日消息,育碧旗下第一人称动作冒险游戏《阿凡达:潘多拉边境(Avatar:FrontiersofPandora)》已于今天登陆Steam平台(点此访问),目前本作正在平台...
- 甜蜜下潜藏的疯狂?和病娇美少女《米塔》在一起的冒险解谜游戏今日发售
-
由Aihasto开发制作,IndieArk发行的冒险解谜游戏《米塔》在今日上架Steam平台进行发售。售价人民币52元,首发-10%的折扣持续14天,折扣后仅需46.8元。该作同步支持日语和俄语配音...
- 十大必玩的合作单机游戏排行
-
合作模式一直是单机游戏中的重要元素,玩家可以和朋友一起组队、配合,共同完成游戏任务。在众多的合作单机游戏中,哪些才是最值得一试的呢?本文将为大家介绍十大必玩的合作单机游戏排行。这些游戏不仅拥有精彩刺激...
- 原版20周年献礼:《战争机器:重装上阵》游戏8月26日发行
-
IT之家5月6日消息,微软官方XboxWire博客昨日(5月5日)发布博文,官宣《战争机器:重装上阵》(GearsofWar:Reloaded)游戏,将于2025年8...
- 十款免费的战斗单机游戏推荐之网络版
-
这篇文章主要介绍了十款免费的战斗单机游戏,并对它们进行了排行。这些游戏涵盖了不同类型和风格,包括角色扮演、射击、策略等。每款游戏都有详细的介绍和评价,读者可以根据自己的喜好选择适合自己的游戏。对于喜欢...
- 十大必玩的合作单机游戏:打造完美团队
-
合作模式一直是单机游戏中的重要元素,玩家可以通过合作来共同完成游戏任务,增加游戏的趣味性和挑战性。在本文中,我们将为您介绍十大必玩的合作单机游戏。这些游戏不仅拥有精彩刺激的剧情和画面,还提供了多种合作...
- 十款好玩的战斗单机游戏:哪个更好玩
-
战斗单机游戏一直是玩家们的最爱,而好玩的战斗单机游戏更是备受期待。在众多的战斗单机游戏中,哪些更好玩呢?本文将为您介绍十款备受好评的战斗单机游戏,并进行详细比较分析。无论您是喜欢动作还是策略,都能在这...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 选择器 (30)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)