3027 字
15 分钟

js的事件循环机制

一、理解进程、线程#

进程是操作系统中的基本概念之一,指的是一个正在运行中的程序,包括了程序的执行代码、数据、资源等。操作系统为每个进程分配一定的系统资源,例如内存空间、文件和设备等,以便进程能够正常运行。

线程是进程中的一个执行流程,可以看作是进程中的一个独立执行单元。每个进程中可以包含多个线程,这些线程共享进程的资源。不同于进程,线程是无法独立存在的,必须依存于进程而存在。线程通过利用进程的资源来执行任务,并可以在进程内进行切换。

简单地说,进程是资源分配和管理的最小单位,而线程是程序执行的最小单位。在多任务环境下,多个进程可以同时执行,同一个进程中的多个线程也可以同时执行。线程的切换比进程的切换开销小,因此多线程的程序更加高效。

二、理解单线程、多线程#

单线程指的是程序只有一个执行线程,只能串行执行任务,即每个任务都得等前一个任务执行完毕后才能进行下一个任务。这种模式的好处是逻辑简单,开发维护成本低,但执行效率较低,特别是在处理大量数据时容易出现阻塞等问题。

多线程指的是程序同时拥有多个执行线程,每个线程可以独立运行,可以同时处理多个任务。多线程可以大大提高程序的执行效率和响应能力,特别是在需要同时处理多个任务或大量数据时非常有用。但多线程的缺点是复杂度高,容易出现并发问题,需要耗费更多的系统资源和开发成本。

单线程适用于简单的应用程序,而多线程则适用于复杂的应用程序,能够大幅提高程序的执行效率和响应能力。

三、理解渲染线程#

渲染线程是指用于渲染图形的计算机进程线程。在Web浏览器中,渲染线程负责将HTML、CSS和JavaScript代码转化为网页上的可视化内容。渲染线程的主要任务是解析HTML文档,确定渲染树和绘制图像。它还负责检查和处理JavaScript代码,以便在网页上进行交互式操作。

渲染线程的作用是在不影响用户界面的情况下,尽可能快地显示用户请求的内容。它要注意避免阻塞用户界面线程,因此需要在后台运行,并尽量减少CPU和内存的使用。

在某些情况下,渲染线程可能需要等待网络请求或文件加载完成,这时可能会导致页面出现卡顿或加载缓慢的情况。为了减少这种情况的发生,渲染线程通常会使用缓存技术,以便在加载相同内容时快速显示网页。

四、理解微任务、宏任务#

微任务和宏任务都是JavaScript事件循环机制中的任务类型。它们之间的区别在于执行的时机和优先级。

宏任务包括一些比较耗时的任务,例如setTimeout、setInterval、AJAX请求、DOM事件等等。这些任务执行完之后,需要等待下一次事件循环开始才能执行下一个任务。执行宏任务时,会先选取队列中最先进入队列的任务执行,直到队列为空。

微任务指的是一些比较短且需要立即执行的任务,例如Promise的then方法、MutationObserver等等。这些任务执行时,会在当前宏任务执行完毕后立即执行。当一个宏任务中产生了微任务,这些微任务会先被放到一个专门的队列中,等待当前宏任务执行完毕时再执行。而在执行这些微任务时,如果又产生了新的微任务,这些新的微任务会被放到队列的末尾,等待执行。

在事件循环开始时,先执行所有的微任务队列中的任务,直到队列为空。然后再执行宏任务队列中的任务。然后再执行微任务队列中的任务,直到队列为空。这个过程会一直重复下去,直到任务队列中和微任务队列中同时为空。

总结来说,微任务具有更高的优先级,会比宏任务优先执行。因此在编写异步代码时,应当注意使用合适的任务类型,以保证代码的正确性和效率。

六、理解同步任务、异步任务#

同步任务是指代码按照顺序执行,每完成一项任务后再进行下一项任务,直到所有任务完成。在同步任务中,代码执行需要等待前一个代码执行完成后才能继续进行下一项任务。

异步任务则是指代码在执行过程中,不必等待前一个任务完成后再执行下一个任务。异步任务可以在单个线程上执行,但可以同时进行多个任务。异步任务通常使用回调函数或Promise来实现异步处理。

举个例子:假设有一个任务列表,包括读取文件、发送数据、等待响应等任务。如果使用同步任务执行,读取文件的任务必须在发送数据的任务完成后才能开始。而在异步任务中,可以在发送数据的同时执行读取文件任务,因此能够更高效地完成任务。

七、理解调用栈#

调用栈是用来跟踪程序执行顺序的一种内存结构。当函数被调用时,它们的相关信息(例如局部变量,返回地址等)会被压入调用栈中,调用栈按照“先进后出”的原则运作。也就是说,当函数返回时,它们的相关信息将从栈中被弹出,以便程序继续执行。通过调用栈,我们可以跟踪程序的执行过程,查看每个函数被调用的顺序以及它们之间的关系。调用栈也是调试程序时重要的工具之一,可以帮助程序员精确定位程序中的问题。

八、JavaScript在设计时就被设计为单线程#

1、简单性:单线程代码容易编写、调试和维护,不容易出现多线程竞争的问题。

2、安全性:多线程需要共享内存,容易造成数据竞争等问题。JavaScript作为一种脚本语言,通常运行在浏览器环境中,存在众多恶意脚本的威胁。如果JavaScript是多线程的,恶意脚本可能会通过共享内存的方式修改其他脚本的数据,从而造成安全问题。

3、可预测性:单线程可以确保事件的执行顺序是可预测的,从而能够避免一些复杂的并发场景。

当然,JavaScript也提供了一些非常重要的异步API,如setTimeout、setInterval、Promise、async/await等,这些API可以模拟多线程的效果,但本质上仍然是单线程。

九、JavaScript为什么需要异步#

1、防止阻塞:JavaScript是单线程语言,如果所有任务都是同步执行的,当执行某个耗时操作(比如网络请求或文件读写)时,整个应用程序会被阻塞,造成用户体验不佳。

2、提升用户体验:异步编程可以使得JavaScript在执行耗时操作的同时,继续响应用户的操作,从而提升用户体验。

3、节约资源:异步编程可以更好地利用计算机资源,通过并行执行多个任务,提高执行效率。

4、支持跨平台开发:JavaScript广泛应用于Web、移动端和后端等不同平台,使用异步编程模式可以支持多种异步事件,从而使得代码具有更好的可移植性。

十、JavaScript中的异步操作有哪些#

  1. 回调函数
  2. Promise
  3. async/await
  4. 事件监听
  5. 定时器
  6. XMLHttpRequest和Fetch API等网络请求
  7. Web Workers(Web Worker API提供了从主执行线程分离并在后台运行脚本的能力,即在后台运行JavaScript代码,不影响页面UI的渲染和响应能力)
  8. Node.js中的异步I/O操作(如读写文件、网络请求等)

十一、JavaScript单线程是如何实现异步的?理解JavaScript事件循环机制#

有了前文基础我们来探讨本文核心事件循环。

JavaScript单线程指的是在同一时刻只能执行一个任务,任务只有在前一个任务执行完毕后才能开始执行。但是JavaScript通过事件循环机制实现了异步。

JavaScript事件循环机制指的是JavaScript运行时环境(ECMAScript规范定义的)按照一定的规则处理代码中的异步操作和事件的机制。JavaScript事件循环机制包含任务队列(Task)、微任务队列(Microtask)和宏任务队列(Macrotask)。

当JavaScript代码执行到一个异步操作或事件时,它并不会立即执行,而是将其放入对应的任务队列中。当当前任务执行完成后,在下一个事件循环的开始,JavaScript会从任务队列中取出一个任务,执行该任务。当任务执行时,可能会产生新的异步操作和事件,这些新的操作也会被放入任务队列中等待执行。

在JavaScript事件循环机制中,任务分为宏任务和微任务。

宏任务包括setTimeout、setInterval、I/O操作等;

微任务包括Promise、MutationObserver、process.nextTick等。

在每次事件循环开始时,JavaScript会先执行所有的微任务队列中的任务,然后再执行宏任务队列中的任务。

一个完整的事件循环流程包括以下步骤:

  1. 从宏任务队列中取出一个任务执行;
  2. 如果该任务中产生了微任务,将它们放入微任务队列中;
  3. 执行微任务队列中的所有任务;
  4. 检查是否需要重新渲染页面;
  5. 重复执行上述步骤,直到任务队列和微任务队列中都没有任务;

事件循环机制是指:

  1. 代码执行时,先执行同步任务,然后将异步任务放入任务队列中,等待执行。
  2. 当所有同步任务执行完毕后,JavaScript引擎会去读取任务队列中的任务。
  3. 将队列中的第一个任务压入执行栈中执行,执行完毕后将其出栈。
  4. 如此循环执行,直到任务队列中的所有任务都执行完毕。

这就是JavaScript实现异步的基本原理,通过将异步任务放到任务队列中,并通过事件循环机制来实现异步执行。

总的来说,JavaScript通过事件循环机制来实现异步操作,将异步任务放到任务队列中,然后在任务队列中等待执行,直到JavaScript引擎空闲,再将任务队列中的任务拿出来执行。

十二、参考链接#

JavaScript——事件循环机制(Event Loop)浅析 - 掘金

https://www.cnblogs.com/kitebear/p/17400025.html

详解事件循环机制(event loop), js运行机制(执行顺序)javascript 事件循环陈吖的博客-CSDN博客

web前端tips:js的事件循环(Event Loop)

JavaScript 中 Event Loop 事件循环机制

事件循环机制 (EventLoop)事件循环原理星屿H的博客-CSDN博客

原文链接:https://blog.csdn.net/snowball_li/article/details/125236024

赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
js的事件循环机制
https://march7th.online/posts/0002-javascript事件循环/
作者
Yiguo
发布于
2024-06-02
许可协议
CC BY-NC-SA 4.0
最后更新于 2024-06-02,距今已过 563 天

部分内容可能已过时

目录