广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >深入理解JavaScript的事件执行机制
  • 495
分享到

深入理解JavaScript的事件执行机制

2024-04-02 19:04:59 495人浏览 独家记忆
摘要

目录前言 浏览器 js 异步执行的原理 浏览器中的事件循环 执行栈与任务队列 宏任务和微任务 Async/await的运行顺序特点示例 个人分析前言 熟悉事件循环,了解浏览器运行机

前言

熟悉事件循环,了解浏览器运行机制将对我们理解 javascript 的执行过程和排查运行问题有很大帮助。以下是总结的一些浏览器事件循环的一些原理和示例。

浏览器 JS 异步执行的原理

  • JS 是单线程的,也就是同一个时刻只能做一件事情,那么,为什么浏览器可以同时执行异步任务呢?
  • 因为浏览器是多线程的,当 JS 需要执行异步任务时,浏览器会另外启动一个线程去执行该任务。
  • 也就是说,JS 是单线程的指的是 执行JS 代码的线程只有一个,是浏览器提供的 JS 引擎线程(主线程)。浏览器中还有定时器线程和 Http 请求线程等,这些线程主要不是来跑 JS 代码的。
  • 比如主线程中需要发一个 ajax 请求,就把这个任务交给另一个浏览器线程(HTTP 请求线程)去真正发送请求,待请求回来了,再将 callback 里需要执行的 JS 回调交给 JS 引擎线程去执行。
  • 即浏览器才是真正执行发送请求这个任务的角色,而 JS 只是负责执行最后的回调处理。所以这里的异步不是 JS 自身实现的,其实是浏览器为其提供的能力。

浏览器中的事件循环

执行栈与任务队列

JS 在解析一段代码时,会将同步代码按顺序排在某个地方,即执行栈,然后依次执行里面的函数。
遇到异步任务时就交给其他线程处理,待当前执行栈所有同步代码执行完成后,会从一个队列中去取出已完成的异步任务的回调加入执行栈继续执行。
遇到异步任务时又交给其他线程,.....,如此循环往复。
而其他异步任务完成后,将回调放入任务队列中待执行栈来取出执行。

宏任务和微任务

根据任务的种类不同,可以分为微任务(micro task)队列和宏任务(Macro task)队列。
事件循环的过程中,执行栈在同步代码执行完成后,优先检查微任务队列是否有任务需要执行,如果没有,再去宏任务队列检查是否有任务执行,如此往复。
微任务一般在当前循环就会优先执行,而宏任务会等到下一次循环,因此,微任务一般比宏任务先执行,并且微任务队列只有一个,宏任务队列可能有多个。另外我们常见的点击和键盘等事件也属于宏任务。

常见宏任务:

  • setTimeout()
  • setInterval()
  • UI交互事件
  • postMessage
  • setImmediate() -- nodejs

常见微任务:

  • promise.then()、promise.catch()
  • new MutaionObserver()
  • process.nextTick() -- nodeJs

如下示例:


console.log('同步代码1');
setTimeout(() => {
    console.log('setTimeout')
}, 0)

new Promise((resolve) => {
  console.log('同步代码2')
  resolve()
}).then(() => {
    console.log('promise.then')
})
console.log('同步代码3');

// 最终输出"同步代码1"、"同步代码2"、"同步代码3"、"promise.then"、"setTimeout"

具体分析如下:

  • setTimeout 回调和 promise.then 都是异步执行的,将在所有同步代码之后执行;
  • 虽然 promise.then 写在后面,但是执行顺序却比 setTimeout 优先,因为它是微任务;
  • new Promise 是同步执行的,promise.then 里面的回调才是异步的。

注意: 在浏览器中 setTimeout 的延时设置为 0 的话,会默认为 4ms,NodeJS 为 1ms。
微任务和宏任务的本质区别:

  • 宏任务特征:有明确的异步任务需要执行和回调;需要其他异步线程支持。
  • 微任务特征:没有明确的异步任务需要执行,只有回调;不需要其他异步线程支持。

Async/await的运行顺序

特点

  • async声明的函数只是把该函数的return包装了,使得无论如何都会返回promise对象(非promise会转化为promise{resolve})。
  • await声明只能用在async函数中。
    • 当执行async函数时,遇到await声明,会先将await后面的内容按照'平常的执行规则'执行完(此处注意,当执行函数内容中又遇到await声明,此时接着执行该await声明内容)。
    • 执行完后立马跳出async函数,去执行主线程其他内容,等到主线程执行完再回到await处继续执行后面的内容。

示例


const a = async () => {
  console.log("a");
  await b();
  await e();
};

const b = async () => {
  console.log("b start");
  await c();
  console.log("b end");
};

const c = async () => {
  console.log("c start");
  await d();
  console.log("c end");
};

const d = async () => {
  console.log("d");
};

const e = async () => {
  console.log("e");
};

console.log('start');
a();
console.log('end');

运行结果

个人分析

  • 在当前同步环境中,先执行console.log('start');输出'start'。
  • 遇到同步函数a(),执行a()。
  • a()是sync/await构造,函数内遇到console.log("a") 输出 'a',遇到await声明 await b(),为异步函数,进入函数b()内执行。(类似的操作,我自己想的)并将 await b()后的内容推入微任务队列中。我们可以记做[await b()后]。
  • b()是sync/await构造,顺序执行遇到console.log("c start") 输出 'c start',遇到await声明 await c(),为异步函数,进入函数c()内执行。并将 await c()后的内容推入微任务队列中。我们可以记做[await c()后, await b()后]。
  • c()是sync/await构造,顺序执行遇到console.log("b start") 输出 'b start',遇到await声明 await d(),为异步函数,进入函数d()内执行。并将 await d()后的内容推入微任务队列中。我们可以记做[await d()后, await c()后, await b()后]。
  • d()中,顺序执行遇到console.log("") 输出 'd',d()函数运行结束。
  • 这是执行完 d()后,无可执行异步函数,此时进入同步环境,执行 a()后的内容。
  • 遇到console.log("end") 输出 'end'。此时同步环境中主线程执行完,检查微任务队列是否有微任务。
  • 微任务队列中[await d()后, await c()后, await b()后]有微任务,执行await d()后的内容。
  • wait d()后的内容是,console.log("c end"), 输出 'c end'。此时内容执行完毕,再从微任务队列中[await c()后, await b()后]检查,执行await c()后的内容。
  • 执行await c()后的内容,console.log("b end");, 输出 'b end'。此时内容执行完毕,再从微任务队列中[await b()后]检查,执行await b()后的内容。
  • await d()后的内容是,await e(),遇到await声明,执行e()。并判断并将 await e()后无运行代码,不用入微任务队列。
  • 执行e(),顺序执行console.log("e");,输出 'e'。此时函数结束。
  • 微任务队列中[]无微任务,执行结束。进入同步环境。

到此这篇关于深入理解JavaScript的事件执行机制的文章就介绍到这了,更多相关JavaScript 事件执行机制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网! 

--结束END--

本文标题: 深入理解JavaScript的事件执行机制

本文链接: https://www.lsjlt.com/news/135453.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • 深入理解JavaScript的事件执行机制
    目录前言 浏览器 JS 异步执行的原理 浏览器中的事件循环 执行栈与任务队列 宏任务和微任务 Async/await的运行顺序特点示例 个人分析前言 熟悉事件循环,了解浏览器运行机...
    99+
    2022-11-12
  • 深入理解JavaScript事件机制
    目录如何实现一个事件的发布订阅介绍下事件循环宏任务和微任务的区别如何实现一个事件的发布订阅 可以通过以下步骤实现 JavaScript 中的发布-订阅模式: 创建一个事件管理器对象。...
    99+
    2023-05-17
    JavaScript事件机制 JS事件机制
  • JavaScript事件流:深入理解事件处理和传播机制
    引言 JavaScript中的事件流是一种机制,用于描述和处理事件在DOM树中的传播过程。了解事件流的属性和工作原理对于编写高效的事件处理代码和实现复杂的交互功能至关重要。本文将详细介绍JavaSc...
    99+
    2023-09-14
    javascript 开发语言 ecmascript 原力计划
  • 深入了解Javascript的事件循环机制
    目录单线程的Javascript同步 vs 异步 宏任务 vs 微任务定时器To Be Continued单线程的Javascript JavaScript是一种单线程语言,它主要用...
    99+
    2022-11-13
  • 深入理解异步事件机制
    通过了解异步设计的由来,来深入理解异步事件机制。 代码地址 什么是异步 同步 并发(Concurrency) 线程(Thread) I/O多路复用 异步(Asynchronous) 回调(Callback) 参考文...
    99+
    2023-01-31
    机制 事件
  • Qt 事件处理机制的深入理解
    目录1.Qt中事件的来源,谁接收处理。2.事件处理顺序3.事件过滤器4.event方法5.鼠标进入事件6.accept(),ignore()1.Qt中事件的来源,谁接收处理。 Qt中...
    99+
    2022-11-13
  • javascript中事件执行机制的示例分析
    小编给大家分享一下javascript中事件执行机制的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!先看一段代码各位小伙...
    99+
    2022-10-19
  • JS的事件循环执行机制详解
    目录前言JS语言的特点JS中同步和异步的使用事件循环是什么?事件循环执行过程微任务和宏任务的区别JS执行/运行机制最后前言 在前端开发中,涉及到JS原生的使用原理是非常重要的知识点,...
    99+
    2023-05-19
    JS事件循环执行机制 JS事件循环 JS事件
  • 深入了解Node事件循环(EventLoop)机制
    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。下面本篇文章就来带大家掌握Node.js中的eventloop,希望对大家有所帮助!虽然js可以在浏览器...
    99+
    2023-05-14
    javascript Node.js 面试 前端
  • 深入阐述JavaScript的运行机制
    JavaScript是一种流行的编程语言,它几乎被用于网站和应用程序的开发中。对于初学者和许多开发人员来说,JavaScript似乎是单线程的,这意味着它只能同时执行一个任务。然而,JavaScript到底是不是真的单线程呢?这是一个有争议...
    99+
    2023-05-14
  • AndroidView的事件分发机制深入分析讲解
    目录1.分发对象-MotionEvent2.如何传递事件1.传递流程2.事件分发的源码解析1.Activity对点击事件的分发过程2.顶级View对点击事件的分发过程3.主要方法4....
    99+
    2023-01-29
    Android View事件分发机制 Android事件分发
  • 带你深入了解Android的事件分发机制
    Android的事件分发机制是指在Android系统中,如何将用户的触摸事件、按键事件等传递给正确的View进行处理的一套机制。它是Android应用程序中实现交互的重要部分,确保用户的操作能够被正确地捕获和处理。 Android的事件分发...
    99+
    2023-08-18
    android android studio ui 知识图谱 事件分发
  • 深入理解 Android事件分发机制源码(基于9.0)
    touch事件最开始从Activity 的 dispatchTouchEvent() 方法开始的 /frameworks/base/core/java/android/app...
    99+
    2022-06-06
    源码 Android
  • 深入理解Spring Aop的执行顺序
    首先回忆一下 AOP 的常用注解 @Before:前置通知:目标方法之前执行 @After:后置通知:目标方法之后执行 @AfterReturning:返回...
    99+
    2022-11-12
  • Android 事件触发机制的深入学习
     Android 事件触发机制的深入学习最近在研究android的事件触发和传播机制,说来很惭愧,web下的事件太熟悉不过了,可在android中却很郁闷,常用的触摸事件都糊里糊涂的,在网上看了半天,也整理一份,供大家参考:pub...
    99+
    2023-05-31
    android 触发机制 roi
  • 深入了解最常用的JavaScript事件
    目录JavaScript 事件:常用的事件:事件操作总结JavaScript 事件: 事件指的就是当某些组件执行了某些操作后,会触发某些代码的执行。 常用的事件: ...
    99+
    2022-11-12
  • 如何从Javascript事件循环看出Vue.nextTick的原理和执行机制
    今天就跟大家聊聊有关如何从Javascript事件循环看出Vue.nextTick的原理和执行机制,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。抛砖...
    99+
    2022-10-19
  • 深入了解Spring的事务传播机制
    目录Spring 事务传播机制有哪些?事务传播机制使用与演示REQUIRED 使用演示REQUIRED_NEW 使用演示NESTED 使用演示总结Spring 事务传播机制是指,包含...
    99+
    2022-11-13
  • 深入理解spring的AOP机制原理
    前言在软件开发中,散布于应用中多处的功能被称为横切关注点,通常来讲,这些横切关注点从概念上是与应用的业务逻辑相分离的。把这些横切关注点和业务逻辑分离出来正是AOP要解决的问题。AOP能够帮我们模块化横切关注点,换言之,横切关注点可以被描述为...
    99+
    2023-05-31
    spring aop sprin
  • 深入理解Django的信号机制
    目录Django的信号Django信号的使用自定义信号扩展:查看Django信号的接受者扩展:Django内置信号Django的信号 Django的信号机制不同于Linux的信号机制...
    99+
    2023-02-08
    Django 信号机制
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作