我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaScript事件循环实例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaScript事件循环实例分析

这篇文章主要讲解了“JavaScript事件循环实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript事件循环实例分析”吧!

前言

异步函数也是有执行顺序的。本质上来说,JavaScript是单线程语言,不管是在浏览器中还是nodejs环境下。浏览器在执行js代码和渲染DOM节点都是在同一个线程中,执行js代码就无法渲染DOM,渲染DOM的时候就无法执行js代码。如果按照这种同步方式执行,页面的渲染将会出现白屏甚至是报错,特别是遇到一些耗时比较长的网络请求或者js代码,因此在实际开发中一般是通过异步的方式解决。

什么是异步?js是一步一步执行代码的,遇到alert这种阻塞代码时,js将会停止往下执行直到阻塞代码执行完毕。异步就是将函数放在单独的异步队列中,不会产生阻塞,js可以继续往下执行,等到同步代码执行完毕后再执行异步队列中的函数。因此,js会先执行完同步代码,才会执行异步代码。异步函数之间,虽然都是异步,但是还是有相对的执行顺序。

异步函数的执行主要依靠事件循环来处理,本文重点探讨异步的分类(宏任务、微任务)、事件循环以及异步函数的执行顺序。

宏任务

宏任务,也可简单的说成是任务,在下一轮DOM渲染之后执行。常见的宏任务有:

  • setTimeout:设置一个定时器,该定时器会在设置的延迟时间到期后执行一个函数或者指定的代码块。值得注意的是,setTimeout不一定会在延迟时间到达后就立即执行函数,而是会判断执行队列中是否还有函数没有处理,如果没有了并且栈为空,setTimeout才会在延迟时间到达后执行函数。

    // setTimeout 延迟执行不等于到期时立即执行let now = new Date().getSeconds();setTimeout(() => {    console.log('this is setTimeout 0');}, 0);setTimeout(() => {    console.log('this is setTimeout 200');}, 200);while(true) {    if (new Date().getSeconds() - now >= 2) {        console.log('break out while loop');        break;    }}

    运行结果

  • break out while loop
    this is setTimeout 0
    this is setTimeout 200

    先执行同步代码,再执行异步。setTimeout(() => {}, 0)表示0毫秒后立即执行函数,但是当前执行队列中还有未处理完的while循环,因此需要等到while循环执行完毕后,才会根据延迟到期时间执行函数。

  • setInterval:设置定时器,表示在固定的时间间隔内,重复执行某一函数或者特定的代码块。注意使用setInterval有最小延迟时间限制以及确保执行时间要小于间隔时间,如果执行时间无法确定,则应采用递归调用setTimeout的方式代替。

  • 网络请求:只要是指XMLHttpRequest等网络请求

微任务

微任务,在下一轮DOM渲染之前执行,微任务比宏任务更早执。常见的微任务有:

  • promise:表示一个异步操作最终的结果和返回值,可能会失败,也可能成功。异步函数在执行时,什么时候返回结果是不可预料的,Promise把异步操作的返回值和函数关联起来,保证在异步执行结束后会执行对应的函数,并通过函数返回操作值。这种效果就类似于把异步代码“同步执行”。

  • queueMicrotask:将函数添加到微任务队

console.log('start');// 微任务队列Promise.resolve().then(() => {    console.log('promise then');});queueMicrotask(() => {    console.log('queueMicrotask');});console.log('end');

运行结果

start
end
promise then
queueMicrotask

事件循环

因为有异步操作的存在,所以出现了事件循环,如果都是同步操作,一行一行执行代码,事件循环也就失去了用武之地。在了解事件循环前,还需要补充js的执行过程:

JavaScript事件循环实例分析

js在执行代码时,遇到函数就会将其添加到调用栈中,每一帧都会存储当前函数的参数和局部变量,当一个函数执行完毕,则会从调用栈中弹出,直到栈被清空,那么程序也就执行完毕。在执行的过程中,需要的引用数据都是从堆中获取。

在实际开发中,往往是同步代码和异步代码都有。在js执行时,还是从第一行代码开始执行,遇到函数就将其添加到栈中,然后执行同步操作;如果遇到异步函数,则根据其类型,宏任务就添加到宏任务队列,微任务添加到微任务队列。直到同步代码执行完毕,则开始执行异步操作。

异步操作后于同步操作,异步操作内部也是分先后顺序的。总的来说:

  • 微任务先于宏任务执行

  • 微任务与微任务之间根据先后顺序执行,宏任务与宏任务之间根据延迟时间顺序执行

  • 微任务在下一轮DOM渲染前执行,宏任务在下一轮DOM渲染之后执行

  • 每个任务的执行都是一次出栈操作,直到栈被清空

微任务比宏任务先执行

console.log('start');// 宏任务队列setTimeout(() => {    console.log('setTimeout');});// 微任务队列Promise.resolve().then(() => {    console.log('promise then');});console.log('end');// 执行结果startendpromise thensetTimeout

微任务在下一轮DOM渲染前执行,宏任务在之后执行

let div = document.createElement('div');div.innerHTML = 'hello world';document.body.appendChild(div);let divList = document.getElementByTagName('div');console.log('同步任务 length ---', list.length);console.log('start');setTimeout(() => {    console.log('setTimeout length ---', list.length);    alert('宏任务 setTimeout 阻塞'); // 使用alert阻塞js执行});Promise.resolve().then(() => {    console.log('promise then length ---', list.length);    alert('微任务 promise then 阻塞);});console.log('end');

事件循环

event loop会持续监听是否有异步操作,如果有则添加到对应的队列中,等待执行。例如在宏任务中添加微任务,或者在微任务中添加宏任务,当前任务执行完后,可能还会有新的任务添加到事件循环中。

JavaScript事件循环实例分析

宏任务与微任务

  • 微任务中创建宏任务

        new Promise((resolve) => {      console.log('promise 1');      setTimeout(() => {        console.log('setTimeout 1');      }, 500);      resolve();    }).then(() => {      console.log('promise then');      setTimeout(() => {        console.log('setTimeout 2');      }, 0);    });    new Promise((resolve) => {      console.log('promise 2');      resolve();    })

    运行结果

  • promise 1
    promise 2
    promise then
    setTimeout 2
    setTimeout 1

    解析

    js执行代码,遇到两个Promise,则分别添加到微任务队列,同步代码执行完毕。

    在微任务队列中根据先进先出,第一个Promise先执行,遇到setTimeout,则添加到宏任务队列,resolve()返回执行结果并执行then,事件循环将其继续添加到微任务队列;第一个Promise执行完毕,执行第二个Promise。

    继续执行微任务队列,直到清空队列。遇到setTimeout,并将其添加到宏任务队列

    宏任务队列现在有两个任务待执行,由于第二个setTimeout的延迟事件更小,则优先执行第二个;如果相等,则按照顺序执行。

    继续执行宏任务队列,直到清空队列。

  • 宏任务中创建微任务

        setTimeout(() => {      console.log('setTimeout 1');      new Promise((resolve) => {        console.log('promise 1');        resolve();      }).then(() => {        console.log('promise then');      })    }, 500);    setTimeout(() => {      console.log('setTimeout 2');      new Promise((resolve) => {        console.log('promise 2');        resolve();      })    }, 0);

    运行结果

  • setTimeout 2
    promise 2
    setTimeout 1
    promise 1
    promise then

    解析

    js执行代码,遇到两个setTimeout,将其添加到宏任务队列,同步代码执行完毕

    先检查微任务队列中是否有待处理的,刚开始肯定没有,因此直接执行宏任务队列中的任务。第二个为零延迟,需要优先执行。遇到Promise,将其添加到微任务队列。第一个宏任务执行完毕

    在执行第二个宏任务时,微任务队列中已经存在待处理的,因此需要先执行微任务。

    微任务执行完毕,并且延迟时间到期,第一个setTimeout开始执行。遇到Promise,将其添加到微任务队列中

    执行微任务队列中的Promise,执行完毕后遇到then,则将其继续添加到微任务队列

    直到所有微任务执行完毕

  • 宏任务中创建宏任务

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

    运行结果

  • setTimeout 1
    setTimeout 4
    setTimeout 2
    setTimeout 3

    解析

    宏任务中创建宏任务,执行顺序一般来说是按照先后顺序的。对于setTImeout来说,延迟时间相同,则按照先后顺序执行;延迟时间不同,则按照延迟时间的大小先后顺序执行

  • 微任务中创建微任务

        new Promise((resolve) => {      console.log('promise 1');      new Promise((resolve) => {        console.log('promise 2');        resolve();      });      new Promise((resolve) => {        console.log('promise 3');        resolve();      })      resolve();    })

    运行结果

  • promise 1
    promise 2
    promise 3

    解析

    微任务中创建微任务,执行顺序一般来说是按照先后顺序执行的。

感谢各位的阅读,以上就是“JavaScript事件循环实例分析”的内容了,经过本文的学习后,相信大家对JavaScript事件循环实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaScript事件循环实例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JavaScript事件循环实例分析

这篇文章主要讲解了“JavaScript事件循环实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript事件循环实例分析”吧!前言异步函数也是有执行顺序的。本质上来说,Ja
2023-07-02

Javascript单线程和事件循环实例分析

本篇内容介绍了“Javascript单线程和事件循环实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、单线程Javascript 是
2023-07-02

NodeJS事件循环实例分析

这篇文章主要介绍“NodeJS事件循环实例分析”,在日常操作中,相信很多人在NodeJS事件循环实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”NodeJS事件循环实例分析”的疑惑有所帮助!接下来,请跟
2023-06-29

JavaScript之事件循环的示例分析

这篇文章主要介绍JavaScript之事件循环的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!js中的事件循环因为JavaScript是单线程的,同一事件只能执行一种方法,所以会将程序中的方法加入到执行栈中按
2023-06-20

Node.js事件循环实例代码分析

本篇内容主要讲解“Node.js事件循环实例代码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node.js事件循环实例代码分析”吧!通过代码模拟 eventloopconst eventl
2023-07-04

Node.js事件循环机制实例代码分析

这篇文章主要介绍“Node.js事件循环机制实例代码分析”,在日常操作中,相信很多人在Node.js事件循环机制实例代码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node.js事件循环机制实例代码分析
2023-07-04

JavaScript事件循环同步任务与异步任务实例分析

本篇内容介绍了“JavaScript事件循环同步任务与异步任务实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!执行栈与任务队列执行栈姑
2023-07-02

nodejs中事件和事件循环的示例分析

这篇文章主要介绍nodejs中事件和事件循环的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!nodejs中的事件循环虽然nodejs是单线程的,但是nodejs可以将操作委托给系统内核,系统内核在后台处理这些
2023-06-14

JS中事件循环机制的示例分析

小编给大家分享一下JS中事件循环机制的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、JavaScript是单线程的JavaScript 是一种单线程的
2023-06-29

nodejs中事件循环机制的示例分析

这篇文章主要介绍了nodejs中事件循环机制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前端开发离不开JavaScript,Javascript是一种web前端语
2023-06-14

详解JavaScript事件循环

JavaScript事件循环是一种机制,用于处理异步事件和回调函数。它是JavaScript运行时环境的一部分,负责管理事件队列和调用栈。文章中有详细的代码示例,需要的朋友可以参考一下
2023-05-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录