一篇文章让你搞清楚JavaScript事件循环

一篇文章让你搞清楚JavaScript事件循环

什么是事件循环?

JavaScript是一门单线程语言,它有一个主线程执行环境(即全局上下文环境),主线程会按照代码的顺序依次执行。然而,由于JavaScript需要处理UI操作、网络请求、定时器等事件,而这些事件需要等待的时间可能非常长,如果按照阻塞式的方式等待,就会影响用户体验。因此,JavaScript采用异步执行和事件循环机制来解决这个问题。

事件循环是一种执行模型,用于处理JavaScript中异步代码的执行顺序。JavaScript通过异步机制将带有回调函数的异步任务放在任务队列中,主线程开始执行同步任务,当同步任务结束后,JavaScript引擎开始轮询任务队列,如果任务队列中有待处理任务,就将它们推送到主线程中执行,主线程继续执行一遍事件循环后回到等待下一个任务的状态。这就是事件循环的基本流程。

任务队列

常见的任务队列主要有三个:主线程任务队列、微任务队列和宏任务队列。

主线程任务队列

主线程任务队列是一个FIFO队列,主要存储异步任务的回调函数。当主线程执行完当前的同步任务后,会检查主线程任务队列中是否有待处理的函数,如果有,那么主线程将会将这些任务加入到主线程任务队列的末尾,然后处理这些任务。

微任务队列

微任务队列是用于存储带有回调函数的异步任务,这些任务通常是由Promise.then()、请求动画帧和queueMicrotask()方法添加的。当JavaScript执行完所有同步任务和在主线程任务队列中发现了异步任务后,JavaScript引擎先会检查是否存在微任务队列。如果存在微任务,那么它们将会被依次处理,直到微任务队列为空为止。

宏任务队列

宏任务队列用于存放那些需要异步执行的回调函数。主线程任务队列中的回调函数通常会被添加到宏任务队列,此外,像setTimeout()、setInterval()和I/O操作等也会被添加到宏任务队列中。当主线程任务队列中的任务全部执行完毕并且微任务队列中所有任务也执行完毕后,JavaScript引擎会去检查宏任务队列,如果有宏任务,则将队列中的第一个任务加入到主线程任务队列中执行,如果宏任务队列为空,则继续等待新的宏任务的加入。

示例:setTimeout和Promise

接下来,我们使用两个示例来展示事件循环是如何工作的。

示例一:setTimeout

console.log('main1')
setTimeout(() => {
  console.log('timeout')
}, 0)
console.log('main2')

上面的代码会先输出‘main1’,接着输出‘main2’,最后输出‘timeout’。这是因为setTimeout()是一种宏任务,它会被添加到宏任务队列中等待执行,而当前任务队列中的两个console.log()函数是同步的,它们会在当前的任务队列被执行完毕后立即执行。当前任务队列执行完毕后,JavaScript引擎会检查宏任务队列中是否有待处理的任务,如果有,则将它们添加到主线程任务队列中执行。

所以,上面的代码输出的顺序是先输出同步任务中的‘main1’和‘main2’,然后由于setTimeout的回调函数处于宏任务队列中,所以在当前任务队列执行完毕后,JavaScript引擎会去宏任务队列中查找任务,由于宏任务队列中只有一个任务(setTimeout的回调函数),所以将它加入主线程任务队列中执行,在主线程任务队列中执行的时候才输出‘timeout’。

示例二:Promise

console.log('main1')
Promise.resolve().then(() => {
  console.log('promise')
})
console.log('main2')

上面的代码会先输出‘main1’,接着输出‘main2’,最后输出‘promise’。当前任务队列中的console.log()函数是同步的,它们会在当前的任务队列被执行完毕后立即执行,而Promise.resolve().then()方法是一种添加微任务的方式,它会将回调函数添加到微任务队列中等待执行,等整个当前任务队列执行完毕后,JavaScript引擎会去检查微任务队列中是否有待处理任务,如果有,则会依次执行这些微任务。

在上述代码中,当main2执行完毕后,JavaScript引擎会查找微任务队列,并发现存在微任务,然后依次执行微任务队列中的回调函数,于是输出‘promise’。

到此为止,我们已经基本了解了JavaScript事件循环的执行过程以及任务队列的相关概念和使用方法。在实际开发中,了解事件循环的执行过程能够帮助我们更好地理解异步编程模型,从而更好地掌握JavaScript的异步机制。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一篇文章让你搞清楚JavaScript事件循环 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • PHP设置Cookie的HTTPONLY属性方法

    下面是详细讲解“PHP设置Cookie的HTTPONLY属性方法”的完整攻略。 什么是HTTPOnly属性? HTTPOnly属性是一种安全标记,它告诉浏览器只有通过HTTP协议传递给服务器端的Cookie可以被读取,而不能在客户端被读取,以此来预防跨站点脚本攻击。 如何通过PHP设置HTTPOnly属性? PHP通过setcookie()函数设置HTTPO…

    JavaScript 2023年6月11日
    00
  • JS实现给json数组动态赋值的方法示例

    下面是JS实现给json数组动态赋值的方法示例的完整攻略: 1. 确认Json数组的数据结构 首先,在动态给Json数组赋值之前,我们需要了解这个数组的数据结构,确认这个数组中包含哪些属性,以及它们的数据类型。 比如,假设我们要动态给一个名为users的Json数组添加用户数据。那么,我们可以分析一下这个数组的数据结构: [ { "name&quo…

    JavaScript 2023年5月27日
    00
  • javascript getElementById 使用方法及用法

    JavaScript getElementById 使用方法及用法 getElementById()是JavaScript中用于按ID获取HTML元素的方法。本文详细介绍了getElementById()的使用方法及用法。 使用方法 在HTML代码中(通常在或中)指定元素ID,例如: <!DOCTYPE html> <html> &l…

    JavaScript 2023年6月10日
    00
  • JavaScript中Math.SQRT2属性的使用详解

    JavaScript中Math.SQRT2属性的使用详解 一、Math.SQRT2属性是什么? Math.SQRT2属性是JavaScript语言中的一个预定义常量,它表示的是2的平方根。它的值约等于1.4142135623730951。这个属性会与Math对象绑定,因此可以使用Math.SQRT2来访问它。 二、Math.SQRT2属性的使用 1.使用Ma…

    JavaScript 2023年6月10日
    00
  • 给ListBox添加双击事件示例代码

    给ListBox添加双击事件的步骤如下: 1. 添加事件处理方法 在窗体的代码文件中,找到窗体类中的初始化代码(通常是InitializeComponent方法)。 在该方法的末尾添加以下代码,为ListBox对象添加一个名为DoubleClick的事件处理方法: this.listBox1.DoubleClick += new System.EventHa…

    JavaScript 2023年6月11日
    00
  • Javascript Global isFinite() 函数

    以下是关于JavaScript Global对象中isFinite()函数的完整攻略,包括两个示例说明。 JavaScript Global对象中的isFinite()函数 JavaScript Global对象中的isFinite()函数用于判断一个数值是否为有限数值。如果一个值是有限数值,则返回true,否则返回false。isFinite()函数可以用…

    JavaScript 2023年5月11日
    00
  • javascript将浮点数转换成整数的三个方法

    当我们在Javascript开发中需要将浮点数转换成整数时,通常有以下三种方法: 1. 使用parseInt函数 let num = 3.14159; let integer = parseInt(num); console.log(integer); // 3 这种方法使用parseInt函数将浮点数先转换成字符串,然后再将字符串转换成整数,通过截取小数点…

    JavaScript 2023年6月10日
    00
  • javascript 面向对象的JavaScript类

    下面我将为您详细讲解“JavaScript 面向对象的 JavaScript 类”的完整攻略。 什么是面向对象的 JavaScript 类 “面向对象编程(Object-Oriented Programming,缩写 OOP)”是一种程序设计范式,它将真实世界的实体抽象为程序中的对象,并且通过对象之间的交互实现系统的功能。 在 JavaScript 中,面向…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部