面试官😏: 讲一下事件循环 ,顺便做道题🤪

题目

倔友们一起看一下把 ~

面试官 : 讲一下事件循环 , 顺便做了一道题🤪:下面字母的输出顺序是什么 ?

js 复制代码
async function async1() {
  console.log('E'); 
  await async2();
  console.log('F');
}

async function async2() {
  console.log('G');
}

setTimeout(() => console.log('H'), 0);
async1(); 
new Promise((res) => {
  console.log('I'); 
  res();
}).then(() => console.log('J'))

这是一段涉及 JavaScript 中异步操作( async/await 、 Promise 、 setTimeout )的代码,要确定其执行顺序,需要了解这些异步机制的执行原理------ 事件循环机制(Event loop)

答案 : E 、 G 、 I 、 F 、 J 、 H

不清楚的倔友一起往下看 :

事件循环

事件循环是JavaScript中用于

  • 处理异步操作
  • 协调事件处理

在网页开发中,事件循环确保用户界面的响应性。例如,当用户点击按钮时,点击事件作为一个宏任务被放入任务队列,在合适的时机被处理。在处理网络请求时,发起请求是异步操作,不会阻塞其他代码执行,请求完成后,响应数据的处理函数会作为一个宏任务或微任务被放入任务队列,等待执行。

基本概念

JavaScript是单线程语言,同一时间只能执行一个任务,但可以通过事件循环来实现异步操作。事件循环允许JavaScript在执行同步任务的同时,处理各种异步任务,如网络请求、定时器、用户交互等,不会因为某个耗时的操作而阻塞整个程序的运行。

工作原理

  • 执行栈:也叫调用栈,是一种存储函数调用关系的数据结构。当函数被调用时,会被压入执行栈,函数执行完毕后从栈顶弹出。JavaScript引擎会按照顺序执行执行栈中的函数。
  • 任务队列 :包括宏任务队列和微任务队列。
    • 宏任务包括 setTimeout 、 setInterval 、 setImmediate (Node.js环境)、I/O操作、UI渲染等
    • 微任务包括 Promise 的回调、 MutationObserver 等
  • 循环机制 :事件循环首先会检查执行栈 是否为空,如果为空,则检查微任务队列 是否有任务。如果有微任务,就会依次执行微任务队列中的所有任务,直到微任务队列为空。然后,事件循环会检查宏任务队列,从宏任务队列中取出一个宏任务放入执行栈执行,执行完这个宏任务后,再次检查微任务队列并执行其中的任务,如此循环往复。

执行流程图

这张图说明了一下几个点 :

  • 同步代码先执行
  • 异步代码先执行宏任务 , 再执行微任务

这个时候 , 我们再来看这段代码的执行顺序 ,简直是有手就行 ~

首先执行同步代码,遇到 setTimeout(() => console.log('H'), 0); , setTimeout 会将其回调函数放入宏任务队列中,暂不执行。

接着调用 async1() ,进入 async1 函数,首先执行 console.log('E'); ,输出 E 。

然后遇到 await async2(); ,先执行 async2 函数, async2 函数中 console.log('G'); ,输出 G 。此时 await 会暂停 async1 函数的执行,将 async1 函数中 await 后面的代码( console.log('F'); )放入微任务队列中。

继续执行同步代码,遇到 new Promise((res) => { console.log('I'); res(); }).then(() => console.log('J')); , Promise 的构造函数中的 console.log('I'); 会立即执行,输出 I ,并且 Promise 状态变为 fulfilled ,其 then 回调函数会被放入微任务队列中。

此时同步代码执行完毕 ,开始处理微任务队列。先执行 async1 函数中 await 后面被放入微任务队列的 console.log('F'); ,输出 F 。

接着执行 Promise 的 then 回调函数 console.log('J'); ,输出 J 。

微任务队列处理完毕后 ,开始处理宏任务队列,执行 setTimeout 的回调函数 console.log('H'); ,输出 H 。

综上所述,这段代码的执行顺序是: E 、 G 、 I 、 F 、 J 、 H 。

总结

两个点

  • 顺序 :同步代码 => 微任务 => 宏任务
  • 循环 :宏任务 => 微任务 , 没有微任务继续执行宏任务
相关推荐
DARLING Zero two♡3 分钟前
浏览器里跑 AI 语音转写?Whisper Web + cpolar让本地服务跑遍全网
前端·人工智能·whisper
Lovely Ruby28 分钟前
前端er Go-Frame 的学习笔记:实现 to-do 功能(三),用 docker 封装成镜像,并且同时启动前后端数据库服务
前端·学习·golang
深红35 分钟前
玩转小程序AR-实战篇
前端·微信小程序·webvr
银空飞羽35 分钟前
让Trae SOLO全自主学习开发近期爆出的React RCE漏洞靶场并自主利用验证(CVE-2025-55182)
前端·人工智能·安全
钮钴禄·爱因斯晨1 小时前
DevUI 组件生态与 MateChat 智能应用:企业级前端智能化实战
前端
不会写DN1 小时前
存储管理在开发中有哪些应用?
前端·后端
清风细雨_林木木1 小时前
Obsidian 笔试环境配置与使用指南
前端
用户47949283569152 小时前
Vite8来啦,告别 esbuild + Rollup,Vite 8 统一用 Rolldown 了
前端·javascript·vite
枫,为落叶2 小时前
VueRouter前端路由
前端