目录
进程、线程
浏览器内核
JavaScript 引擎是单线程
JavaScript 事件循环机制
首页 web前端 js教程 JS浏览器事件循环机制

JS浏览器事件循环机制

Jul 07, 2018 pm 05:11 PM
javascript 前端 浏览器

这篇文章主要介绍了关于JS浏览器事件循环机制,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

先来明白些概念性内容。

进程、线程

  • 进程是系统分配的独立资源,是 CPU 资源分配的基本单位,进程是由一个或者多个线程组成的。

  • 线程是进程的执行流,是CPU调度和分派的基本单位,同个进程之中的多个线程之间是共享该进程的资源的。

浏览器内核

  • 浏览器是多进程的,浏览器每一个 tab 标签都代表一个独立的进程(也不一定,因为多个空白 tab 标签会合并成一个进程),浏览器内核(浏览器渲染进程)属于浏览器多进程中的一种。

  • 浏览器内核有多种线程在工作。

    • http 请求的时候会开启一条请求线程。

    • 请求完成有结果了之后,将请求的回调函数添加到任务队列中,等待 JS 引擎处理。

    • 浏览器定时计数器并不是由 JS 引擎计数的,阻塞会导致计时不准确。

    • 开启定时器触发线程来计时并触发计时,计时完成后会被添加到任务队列中,等待 JS 引擎处理。

    • 当事件符合触发条件被触发时,该线程会把对应的事件回调函数添加到任务队列的队尾,等待 JS 引擎处理。

    • 单线程工作,负责解析运行 JavaScript 脚本。

    • 和 GUI 渲染线程互斥,JS 运行耗时过长就会导致页面阻塞。

    • 负责渲染页面,解析 HTML,CSS 构成 DOM 树等,当页面重绘或者由于某种操作引起回流都会调起该线程。

    • 和 JS 引擎线程是互斥的,当 JS 引擎线程在工作的时候,GUI 渲染线程会被挂起,GUI 更新被放入在 JS 任务队列中,等待 JS 引擎线程空闲的时候继续执行。

    • GUI 渲染线程:

    • JS 引擎线程:

    • 事件触发线程:

    • 定时器触发线程:

    • http 请求线程:

2778021867-5b405151e0c2f_articlex[1].png

JavaScript 引擎是单线程

JavaScript 引擎是单线程,也就是说每次只能执行一项任务,其他任务都得按照顺序排队等待被执行,只有当前的任务执行完成之后才会往下执行下一个任务。

HTML5 中提出了 Web-Worker API,主要是为了解决页面阻塞问题,但是并没有改变 JavaScript 是单线程的本质。了解 Web-Worker。

JavaScript 事件循环机制

JavaScript 事件循环机制分为浏览器和 Node 事件循环机制,两者的实现技术不一样,浏览器 Event Loop 是 HTML 中定义的规范,Node Event Loop 是由 libuv 库实现。这里主要讲的是浏览器部分。

Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。

  • JS 调用栈

    JS 调用栈是一种后进先出的数据结构。当函数被调用时,会被添加到栈中的顶部,执行完成之后就从栈顶部移出该函数,直到栈内被清空。

  • 同步任务、异步任务

    JavaScript 单线程中的任务分为同步任务和异步任务。同步任务会在调用栈中按照顺序排队等待主线程执行,异步任务则会在异步有了结果后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候,也就是栈内被清空的时候,被读取到栈中等待主线程执行。任务队列是先进先出的数据结构。

  • Event Loop

    调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。

1387142244-5a75a1f21e0d8_articlex[1].png

3533685253-5b4050ee91208_articlex[1].png

  • 定时器

    定时器会开启一条定时器触发线程来触发计时,定时器会在等待了指定的时间后将事件放入到任务队列中等待读取到主线程执行。

    定时器指定的延时毫秒数其实并不准确,因为定时器只是在到了指定的时间时将事件放入到任务队列中,必须要等到同步的任务和现有的任务队列中的事件全部执行完成之后,才会去读取定时器的事件到主线程执行,中间可能会存在耗时比较久的任务,那么就不可能保证在指定的时间执行。

  • 宏任务(macro-task)、微任务(micro-task)

    除了广义的同步任务和异步任务,JavaScript 单线程中的任务可以细分为宏任务和微任务。

    macro-task包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。

    micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver。

        console.log(1);
        setTimeout(function() {
            console.log(2);
        })
        var promise = new Promise(function(resolve, reject) {
            console.log(3);
            resolve();
        })
        promise.then(function() {
            console.log(4);
        })
        console.log(5);
    登录后复制

    示例中,setTimeout 和 Promise被称为任务源,来自不同的任务源注册的回调函数会被放入到不同的任务队列中。

    有了宏任务和微任务的概念后,那 JS 的执行顺序是怎样的?是宏任务先还是微任务先?

    第一次事件循环中,JavaScript 引擎会把整个 script 代码当成一个宏任务执行,执行完成之后,再检测本次循环中是否寻在微任务,存在的话就依次从微任务的任务队列中读取执行完所有的微任务,再读取宏任务的任务队列中的任务执行,再执行所有的微任务,如此循环。JS 的执行顺序就是每次事件循环中的宏任务-微任务。

    • 上面的示例中,第一次事件循环,整段代码作为宏任务进入主线程执行。

    • 遇到了 setTimeout ,就会等到过了指定的时间后将回调函数放入到宏任务的任务队列中。

    • 遇到 Promise,将 then 函数放入到微任务的任务队列中。

    • 整个事件循环完成之后,会去检测微任务的任务队列中是否存在任务,存在就执行。

    • 第一次的循环结果打印为: 1,3,5,4。

    • 接着再到宏任务的任务队列中按顺序取出一个宏任务到栈中让主线程执行,那么在这次循环中的宏任务就是 setTimeout 注册的回调函数,执行完这个回调函数,发现在这次循环中并不存在微任务,就准备进行下一次事件循环。

    • 检测到宏任务队列中已经没有了要执行的任务,那么就结束事件循环。

    • 最终的结果就是 1,3,5,4,2。

    以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

    相关推荐:

    JS定时器和单线程异步特性

以上是JS浏览器事件循环机制的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

apache服务器是什么 apache服务器是干嘛的 apache服务器是什么 apache服务器是干嘛的 Apr 13, 2025 am 11:57 AM

Apache服务器是强大的Web服务器软件,充当浏览器与网站服务器间的桥梁。1. 它处理HTTP请求,根据请求返回网页内容;2. 模块化设计允许扩展功能,例如支持SSL加密和动态网页;3. 配置文件(如虚拟主机配置)需谨慎设置,避免安全漏洞,并需优化性能参数,例如线程数和超时时间,才能构建高性能、安全的Web应用。

HDFS文件系统在CentOS上的使用技巧 HDFS文件系统在CentOS上的使用技巧 Apr 14, 2025 pm 07:30 PM

CentOS系统下HDFS文件系统的安装、配置及优化指南本文将指导您如何在CentOS系统上安装、配置和优化Hadoop分布式文件系统(HDFS)。HDFS安装与配置Java环境安装:首先,确保已安装合适的Java环境。编辑/etc/profile文件,添加以下内容,并将/usr/lib/java-1.8.0/jdk1.8.0_144替换为您的实际Java安装路径:exportJAVA_HOME=/usr/lib/java-1.8.0/jdk1.8.0_144exportPATH=$J

了解React的主要功能:前端视角 了解React的主要功能:前端视角 Apr 18, 2025 am 12:15 AM

React的主要功能包括组件化思想、状态管理和虚拟DOM。1)组件化思想允许将UI拆分成可复用的部分,提高代码可读性和可维护性。2)状态管理通过state和props管理动态数据,变化触发UI更新。3)虚拟DOM优化性能,通过内存中的DOM副本计算最小操作更新UI。

解决 Craft CMS 中的缓存问题:使用 wiejeben/craft-laravel-mix 插件 解决 Craft CMS 中的缓存问题:使用 wiejeben/craft-laravel-mix 插件 Apr 18, 2025 am 09:24 AM

在使用CraftCMS开发网站时,常常会遇到资源文件缓存的问题,特别是当你频繁更新CSS和JavaScript文件时,旧版本的文件可能仍然被浏览器缓存,导致用户无法及时看到最新的更改。这个问题不仅影响用户体验,还会增加开发和调试的难度。最近,我在项目中遇到了类似的困扰,经过一番探索,我找到了wiejeben/craft-laravel-mix这个插件,它完美地解决了我的缓存问题。

Nginx性能监控与故障排查工具使用 Nginx性能监控与故障排查工具使用 Apr 13, 2025 pm 10:00 PM

Nginx性能监控与故障排查主要通过以下步骤进行:1.使用nginx-V查看版本信息,并启用stub_status模块监控活跃连接数、请求数和缓存命中率;2.利用top命令监控系统资源占用,iostat和vmstat分别监控磁盘I/O和内存使用情况;3.使用tcpdump抓包分析网络流量,排查网络连接问题;4.合理配置worker进程数,避免并发处理能力不足或进程上下文切换开销过大;5.正确配置Nginx缓存,避免缓存大小设置不当;6.通过分析Nginx日志,例如使用awk和grep命令或ELK

Debian OpenSSL如何配置HTTPS服务器 Debian OpenSSL如何配置HTTPS服务器 Apr 13, 2025 am 11:03 AM

在Debian系统上配置HTTPS服务器涉及几个步骤,包括安装必要的软件、生成SSL证书、配置Web服务器(如Apache或Nginx)以使用SSL证书。以下是一个基本的指南,假设你使用的是ApacheWeb服务器。1.安装必要的软件首先,确保你的系统是最新的,并安装Apache和OpenSSL:sudoaptupdatesudoaptupgradesudoaptinsta

如何在CentOS上监控HDFS状态 如何在CentOS上监控HDFS状态 Apr 14, 2025 pm 07:33 PM

在CentOS系统上监控HDFS(Hadoop分布式文件系统)状态有多种途径。本文将介绍几种常用方法,助您选择最合适的方案。1.利用Hadoop自带的WebUIHadoop自带的Web界面提供集群状态监控功能。步骤:确保Hadoop集群已启动并运行。访问WebUI:在浏览器中输入http://:50070(Hadoop2.x)或http://:9870(Hadoop3.x)。默认用户名和密码通常为hdfs/hdfs。2.命令行工具监控Hadoop提供一系列命令行工具,方便监

Tomcat日志中如何查看线程状态 Tomcat日志中如何查看线程状态 Apr 13, 2025 am 08:36 AM

要查看Tomcat日志中的线程状态,您可以采用以下几种方法:TomcatManagerWeb界面:在浏览器中输入Tomcat的管理地址(通常为http://localhost:8080/manager),登录后即可查看线程池的状态。JMX监控:使用JMX监控工具(如JConsole)连接到Tomcat的MBean服务器,查看Tomcat线程池的状态。在JConsole中选择

See all articles