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

题目

倔友们一起看一下把 ~

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

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 。

总结

两个点

  • 顺序 :同步代码 => 微任务 => 宏任务
  • 循环 :宏任务 => 微任务 , 没有微任务继续执行宏任务
相关推荐
数字化顾问5 分钟前
解析前端框架 Axios 的设计理念与源码:从零手写一个支持 HTTP/3 的“类 Axios”最小核
前端
二个半engineer10 分钟前
微前端中iframe集成方式与使用微前端框架方式对比
前端·前端框架
我是华为OD~HR~栗栗呀16 分钟前
测试转C++开发面经(华为OD)
java·c++·后端·python·华为od·华为·面试
小菜全21 分钟前
《WebAssembly:前端开发的新可能》
前端·javascript
Dream it possible!26 分钟前
LeetCode 面试经典 150_哈希表_快乐数(45_202_C++_简单)(哈希表;快慢指针)
leetcode·面试·散列表
余防26 分钟前
CSRF跨站请求伪造
前端·安全·web安全·csrf
兮山与31 分钟前
前端2.0
前端
南风木兮丶38 分钟前
Vue 项目安装 @antfu/eslint-config 保姆级教程
前端·javascript·vue.js
万少1 小时前
记 HarmonyOS 开发中的一个小事件 怒提华为工单
前端·harmonyos
未来之窗软件服务1 小时前
万象EXCEL开发(六)excel单元格运算逻辑 ——东方仙盟金丹期
前端·excel·仙盟创梦ide·东方仙盟·万象excel