博客
关于我
JavaScript之运行机制,以及Event-Loop的讲解
阅读量:194 次
发布时间:2019-02-28

本文共 2184 字,大约阅读时间需要 7 分钟。

JavaScript事件循环机制详解

引入题目

在学习JavaScript时,很多开发者会遇到一个难以理解的问题:代码中某些操作会导致输出顺序与预期不符。例如,以下代码:

console.log(1); setTimeout(() => {    console.log(2)}, 0); console.log(3);

打印的顺序是1、3、2,而不是我们直觉上认为的1、2、3。这一现象的背后是JavaScript的单线程执行机制和事件循环机制的深层原理。接下来,我们将从基础到高级深入探讨JavaScript的运行机制。

单线程与JavaScript的运行机制

单线程的定义

单线程指的是在同一时间内,只能执行一项任务。JavaScript选择单线程作为其主要执行模型的原因在于其主要用于与用户交互和操作DOM(文档对象模型)。如果采用多线程,会引入复杂的同步问题,例如同时修改DOM时可能导致的数据不一致。

单线程的含义

单线程意味着所有任务必须排队等待前一个任务完成才能执行。这种机制虽然简单,但在处理大量异步任务时可能导致性能问题。因此,JavaScript引入了任务队列来处理异步任务。

任务队列的概念

任务队列是用来管理异步任务的容器。异步任务被分为两类:

  • 同步任务(Synchronous Task):直接在主线程上执行的任务,例如console.log()、DOM操作等。
  • 异步任务(Asynchronous Task):不直接在主线程上执行的任务,例如setTimeout()、网络请求等,这些任务会被放入任务队列中,等待主线程空闲时执行。
  • 任务队列的执行顺序

    任务队列中的任务按照先进先出的原则执行。当主线程完成所有同步任务后,会去任务队列中取出最早的异步任务进行执行。

    Event Loop的工作原理

    Event Loop是JavaScript执行异步任务的核心机制。它的执行过程可以分为以下几个阶段:

  • 执行当前宏任务(Macro Task):主线程执行当前脚本中的同步代码。
  • 处理微任务(Micro Task):在宏任务执行完成后,立即处理任务队列中的微任务。
  • 重复上述步骤直到所有任务完成:直到所有宏任务和微任务都被处理完毕,Event Loop才会终止。
  • 宏任务与微任务

    宏任务包括:

    • 主脚本(Script)的执行代码
    • setTimeout()
    • setInterval()
    • setImmediate()
    • I/O操作
    • UI渲染

    微任务包括:

    • process.nextTick()
    • Promise
    • MutationObserver

    宏任务和微任务的执行顺序

  • 执行当前宏任务。
  • 处理任务队列中的所有微任务。
  • 进入下一个宏任务循环。
  • 宏任务与微任务的执行顺序示例

    以下代码:

    setTimeout(() => {    console.log('a');}, 0);Promise.resolve().then(() => {    console.log('b');}).then(() => {    Promise.resolve('c').then((data) => {        setTimeout(() => {            console.log('d');        }, 0);        console.log('e');        return data;    }).then((data) => {        console.log(data);    });new Promise((resolve) => {    console.log('f');    resolve('g');}).then((res) => {    console.log(res);});console.log('h');

    将打印出:f, h, b, g, e, c, a, d。这是因为:

  • console.log('h')是主线程中的同步任务,立即执行。
  • fPromise中的同步代码,立即执行。
  • bg是同一个then链中的微任务,按顺序执行。
  • ecthen链中的同步操作。
  • adsetTimeout触发,按顺序执行。
  • 题目2解析

    以下代码:

    console.log(1);let a = setTimeout(() => {    console.log(2);}, 0);console.log(3);Promise.resolve(4).then(() => {    console.log(b);    clearTimeout(a);});console.log(5);

    打印结果为:1, 3, 5, 4。原因在于:

  • console.log(1)console.log(3)是同步任务,按顺序执行。
  • setTimeout生成的a被立即放入任务队列。
  • Promise.resolve(4)生成一个新的then,在clearTimeout(a)之前执行。
  • clearTimeout(a)确保在a执行完成后取消定时任务。
  • 通过以上分析,我们可以清晰地理解JavaScript事件循环机制的运行原理及其在实际开发中的应用。掌握这些知识对于优化和调试JavaScript代码至关重要。

    转载地址:http://wgni.baihongyu.com/

    你可能感兴趣的文章
    Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
    查看>>
    Nginx配置如何一键生成
    查看>>
    Nginx配置实例-负载均衡实例:平均访问多台服务器
    查看>>
    NHibernate学习[1]
    查看>>
    NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
    查看>>
    NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
    查看>>
    NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
    查看>>
    NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
    查看>>
    NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
    查看>>
    NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
    查看>>
    Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
    查看>>
    NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
    查看>>
    NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
    查看>>
    NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
    查看>>
    NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
    查看>>
    NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
    查看>>
    NIH发布包含10600张CT图像数据库 为AI算法测试铺路
    查看>>
    Nim教程【十二】
    查看>>
    Nim游戏
    查看>>