当前位置: 首页 > news >正文

JavaScript事件循环机制

一、JavaScript执行机制基础

1. 单线程与异步

JavaScript设计之初就是为了在浏览器中处理DOM操作,为了避免复杂的线程同步问题,采用了单线程模型。这意味着JS代码是按顺序执行的,同一时间只能做一件事。

console.log('1');
console.log('2');
// 输出顺序永远是1, 2

但单线程并不意味着阻塞,JavaScript通过事件循环机制实现了异步非阻塞的执行模式。

2. 调用栈与任务队列

  • 调用栈(Call Stack):存储同步任务的执行上下文,后进先出(LIFO)
  • 任务队列(Task Queue):存储异步任务的回调函数,先进先出(FIFO)

当调用栈为空时,事件循环会从任务队列中取出任务压入调用栈执行。

二、同步代码与异步代码

1. 同步代码执行

同步代码会立即进入调用栈执行:

function func1() {console.log('func1');
}function func2() {func1();console.log('func2');
}func2();
// 输出顺序: func1, func2

2. 异步代码类型

常见的异步操作包括:

  • 定时器:setTimeout, setInterval
  • 网络请求:Ajax, Fetch
  • DOM事件:click, load等
  • Promise
  • async/await
console.log('Start');setTimeout(() => {console.log('Timeout');
}, 0);Promise.resolve().then(() => {console.log('Promise');
});console.log('End');
// 输出顺序: Start, End, Promise, Timeout

三、宏任务与微任务

1. 宏任务(MacroTask)

包括:

  • js脚本执行事件
  • setTimeout setInterval
  • AJAX请求完成事件
  • 用户交互事件

2. 微任务(MicroTask)

包括:

  • Promise.then/catch/finally
  • process.nextTick(Node.js环境)
  • MutationObserver

3. 执行顺序规则

  1. 执行一个宏任务(通常是script整体代码)
  2. 执行过程中遇到微任务,加入微任务队列;遇到宏任务,加入宏任务队列
  3. 当前宏任务执行完毕,立即执行所有微任务
  4. 进行UI渲染(浏览器环境)
  5. 从宏任务队列取出下一个宏任务执行
console.log('script start'); // 宏任务1开始setTimeout(function() {console.log('setTimeout'); // 宏任务2
}, 0);Promise.resolve().then(function() {console.log('promise1'); // 微任务1
}).then(function() {console.log('promise2'); // 微任务2
});console.log('script end'); // 宏任务1结束/*
输出顺序:
script start
script end
promise1
promise2
setTimeout
*/

四、典型面试题解析

题目1:基础执行顺序

console.log('1');setTimeout(function() {console.log('2');new Promise(function(resolve) {console.log('3');resolve();}).then(function() {console.log('4');});
}, 0);new Promise(function(resolve) {console.log('5');resolve();
}).then(function() {console.log('6');
});setTimeout(function() {console.log('7');
}, 0);console.log('8');

解析过程

  1. 同步代码执行:

    • 输出1
    • 输出5(Promise构造函数是同步的)
    • 输出8
  2. 微任务队列:

    • then回调:输出6
  3. 宏任务队列:

    • 第一个setTimeout:
      • 输出2
      • Promise构造函数输出3
      • then回调(微任务):输出4
    • 第二个setTimeout:
      • 输出7

最终输出顺序:1, 5, 8, 6, 2, 3, 4, 7

题目2:async/await执行顺序

async function async1() {console.log('async1 start');await async2();console.log('async1 end');
}async function async2() {console.log('async2');
}console.log('script start');setTimeout(function() {console.log('setTimeout');
}, 0);async1();new Promise(function(resolve) {console.log('promise1');resolve();
}).then(function() {console.log('promise2');
});console.log('script end');

解析过程

  1. 同步代码:

    • 输出script start
    • 调用async1(),输出async1 start
    • 调用async2(),输出async2
    • await后面的代码相当于Promise.then,放入微任务队列
    • Promise构造函数输出promise1
    • then回调放入微任务队列
    • 输出script end
  2. 微任务队列:

    • async1 end
    • promise2
  3. 宏任务队列:

    • setTimeout输出setTimeout

最终输出顺序
script start, async1 start, async2, promise1, script end, async1 end, promise2, setTimeout

http://www.lryc.cn/news/597307.html

相关文章:

  • 免费下载入户申请书,轻松办理登记手续——“文件扫描助手”网站介绍
  • 使用 piano_transcription_inference将钢琴录音转换为 MIDI
  • 开闭原则在C++中的实现
  • 基于Tornado的WebSocket实时聊天系统:从零到一构建与解析
  • 【js(5)原型与原型链】
  • 自由学习记录(72)
  • JavaEE Spring框架的概述与对比无框架下的优势
  • 大模型开发
  • 【Ansible】Ansible 管理 Elasticsearch 集群启停
  • NAPI node-addon-api 编译报错 error C1083: “napi.h”: No such file or directory
  • 【esp32s3】GPIO 寄存器 开发解析
  • MACOS安装配置Gradle
  • 垃圾回收介绍
  • static 关键字的 特殊性
  • 双流join 、 Paimon Partial Update 和 动态schema
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-2,(电路分析/MOS管)
  • OpenLayers 快速入门(四)View 对象
  • PyTorch中nn.Module详解和综合代码示例
  • 大模型提示词漏洞攻防实战:从注入攻击到智能免疫系统的进化之路
  • mac电脑搭载c、c++环境(基于vs code)
  • 在mac 上zsh 如何安装最新的 go 工具
  • GRE实验
  • 微软Fabric重塑数据管理:Forrester报告揭示高ROI
  • 「iOS」——KVC
  • linxu CentOS 配置nginx
  • 【音视频学习】四、深入解析视频技术中的YUV数据存储方式:从原理到实践
  • 开源UI生态掘金:从Ant Design二次开发到行业专属组件的技术变现
  • 7月23日华为机考真题第二题-200分
  • 7月23日华为机考真题第一题100分
  • 关于原车一键启动升级手机控车的核心信息及注意事项