了解事件循环

2023-12-23

我正在思考这个问题,这就是我想到的:

我们看下面这段代码:

console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);

有请求进来,JS引擎开始一步步执行上面的代码。前两个调用是同步调用。但当谈到setTimeout方法,它变成异步执行。但JS立即从中返回并继续执行,这就是所谓的Non-Blocking or Async。它还继续致力于其他工作等。

本次执行的结果如下:

a c d b

所以基本上是第二个setTimeout首先完成,并且它的回调函数比第一个函数更早执行,这是有道理的。

我们这里讨论的是单线程应用程序。 JS 引擎会继续执行此操作,除非完成第一个请求,否则不会执行第二个请求。但好处是它不会等待像这样的阻塞操作setTimeout解决,因此速度会更快,因为它接受新的传入请求。

但我的问题围绕以下几点出现:

#1:如果我们谈论的是单线程应用程序,那么什么机制处理setTimeouts而JS引擎接受更多请求并执行它们?单线程如何继续处理其他请求?什么起作用setTimeout而其他请求不断传入并被执行。

#2:如果这些setTimeout当更多请求传入并执行时,函数在幕后执行,什么在幕后执行异步执行?我们谈论的这个东西是什么?EventLoop?

#3:但是整个方法不应该放在EventLoop这样整个事情就会被执行并调用回调方法?这就是我在谈论回调函数时的理解:

function downloadFile(filePath, callback)
{
   blah.downloadFile(filePath);
   callback();
}

但在这种情况下,JS引擎如何知道它是否是一个异步函数,以便将回调放在EventLoop?也许像asyncC# 中的关键字或某种属性,指示 JS 引擎将采用的方法是异步方法,应进行相应处理。

#4: But an article http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027与我对事情可能如何运作的猜测完全相反:

事件循环是回调函数的队列。当异步 函数执行时,回调函数被推入队列。这 JavaScript 引擎不会开始处理事件循环,直到 执行异步函数后的代码。

#5:这里有一张图片可能会有所帮助,但图片中的第一个解释与问题 4 中提到的内容完全相同:

所以我的问题是对上面列出的项目进行一些澄清?


1:如果我们谈论的是单线程应用程序,那么当JS引擎接受更多请求并执行它们时,什么处理setTimeouts?那单线程不是会继续处理其他请求吗?那么当其他请求不断到来并被执行时,谁将继续处理 setTimeout 。

节点进程中只有 1 个线程实际执行程序的 JavaScript。然而,在节点本身内部,实际上有几个线程处理事件循环机制的操作,其中包括一个 IO 线程池和一些其他线程。关键是这些线程的数量与正在处理的并发连接的数量并不对应,就像在每个连接的线程并发模型中一样。

现在关于“执行 setTimeouts”,当您调用setTimeout,所有节点所做的基本上就是更新将来某个时间要执行的函数的数据结构。它基本上有一堆需要做的事情的队列,事件循环的每个“滴答声”都会选择一个,将其从队列中删除,然后运行它。

需要理解的关键一点是,节点依赖操作系统来完成大部分繁重的工作。因此,传入的网络请求实际上是由操作系统本身跟踪的,当节点准备好处理请求时,它只使用系统调用向操作系统请求网络请求,并准备好处理数据。 IO“工作”节点所做的大部分工作都是“嘿操作系统,有一个网络连接,数据已准备好读取?”或“嘿操作系统,我的任何未完成的文件系统调用都已准备好数据吗?”。基于其内部算法和事件循环引擎设计,节点将选择 JavaScript 的一个“tick”来执行、运行它,然后再次重复该过程。这就是事件循环的含义。 Node 基本上始终在确定“我应该运行的下一段 JavaScript 是什么?”,然后运行它。这会影响操作系统已完成的 IO,以及通过调用在 JavaScript 中排队的内容setTimeout or process.nextTick.

2:如果这些setTimeout将在幕后执行,同时更多的请求传入并执行,那么幕后执行异步执行的就是我们正在谈论的EventLoop?

JavaScript 不会在幕后执行。程序中的所有 JavaScript 都在前端和中心运行,一次运行一个。幕后发生的事情是操作系统处理 IO,节点等待其准备就绪,节点管理其等待执行的 javascript 队列。

3:JS引擎如何知道它是否是一个异步函数,以便将其放入EventLoop中?

节点核心中有一组固定的异步函数,因为它们进行系统调用,并且节点知道这些函数是哪些,因为它们必须调用操作系统或 C++。基本上,所有网络和文件系统 IO 以及子进程交互都将是异步的,JavaScript 使 Node 异步运行某些内容的唯一方法是调用 Node 核心库提供的异步函数之一。即使您使用定义了自己的 API 的 npm 包,为了产生事件循环,最终该 npm 包的代码将调用节点核心的异步函数之一,此时节点知道刻度已完成并且可以启动事件再次循环算法。

4 事件循环是一个回调函数队列。当异步函数执行时,回调函数被推入队列。在执行异步函数之后的代码之前,JavaScript 引擎不会开始处理事件循环。

是的,这是事实,但它具有误导性。关键是正常模式是:

//Let's say this code is running in tick 1
fs.readFile("/home/barney/colors.txt", function (error, data) {
  //The code inside this callback function will absolutely NOT run in tick 1
  //It will run in some tick >= 2
});
//This code will absolutely also run in tick 1
//HOWEVER, typically there's not much else to do here,
//so at some point soon after queueing up some async IO, this tick
//will have nothing useful to do so it will just end because the IO result
//is necessary before anything useful can be done

所以,是的,您可以通过在同一时间同步计算内存中的斐波那契数来完全阻止事件循环,是的,这会完全冻结您的程序。这是合作并发。 JavaScript 的每次更新都必须在合理的时间内产生事件循环,否则整个架构就会失败。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解事件循环 的相关文章

随机推荐

  • google+ 分享和 onendinteraction - 无需确认

    我正在设置一个 google 分享按钮 并想知道何时有人分享了该链接 以便我可以执行操作 您可以使用以下命令在共享按钮上注册回调onendinteraction属性 并且文档指出 只要共享框关闭以及共享完成 就会调用此函数 我的函数是在窗口
  • Tensorflow 无法工作:无法加载动态库“nvcuda.dll”; dlerror:找不到 nvcuda.dll

    几周前 我安装了适用于 CPU Windows 的 TensorFlow 并且运行良好 然而 今天我尝试为 GPU 安装它 但我的 GPU 不受支持 所以我删除了 GPU 版本并重新安装了 CPU 版本 现在 当我尝试运行一个简单的卷积神经
  • 在 Tomcat 中运行后台 Java 程序 [重复]

    这个问题在这里已经有答案了 有人可以在这里提供建议吗 我遇到过这样的情况 用户将通过 Java JSP 和 servlet 以交互方式向我的应用程序提交数据挖掘请求 该应用程序将动态计算出数据等的关联规则 由于这样的工作可能需要一段时间 我
  • PHP 中的分段错误(核心转储)

    好的 我正在 Ubuntu 上的命令行上运行 PHP 应用程序 它以 分段错误 核心转储 结束 我该如何从这里开始调试它 我很确定没有内存泄漏 因为我已经使用 get memory usage 检查过它 编辑 好吧 正如 Brendan 和
  • 什么决定(如何配置)php PDO 驱动程序对日期和时间戳字段的值使用什么格式字符串?

    我有 Firebird 3 0 数据库 其中包含日期和时间戳字段 并且我正在使用 interbase 扩展 是的 仍然是 interbase 和 PHP 7 x 中的 Yii2 框架 我有 Yii 代码 Yii app gt db gt c
  • Rails - 删除未保存的关联记录

    假设我有一个包含很多文章的用户模型 如果我多次调用 user articles new 我将有许多与该用户关联的未保存的文章对象 当您运行 user articles 时 它们是可见的 调用 user save 将保存所有未保存的记录 如何
  • 使用 LINQ 展平分层数据集 - 但需要注意

    我有以下数据集 需要将其展平为列表
  • Java 中的 RegEx:如何处理换行符

    我目前正在尝试学习如何使用正则表达式 所以请忍受我的简单问题 例如 假设我有一个输入文件 其中包含一堆由换行符分隔的链接 www foo com Archives monkeys htmMonkey 网站的描述 www foo com Ar
  • java.io.IOException:不支持标记/重置

    这段代码不起作用 我已经准备好一堂课了 因为它可以找到here http javafree uol com br topic 879623 Executar wav html 但音乐不起作用 我怎样才能解决这个问题 private void
  • 如何检查我的 Python Discord 机器人是否具有必要的权限?

    我制作了一个实用机器人来帮助记录消息并帮助将通道从一台服务器迁移到另一台服务器 我需要检查它是否具有执行命令所需的权限 但以下代码不起作用 我使用 client event并且不想使用 bot command 这是我的权限检查代码 if n
  • 如何在调用sqlcmd时更改端口

    我有这个命令 sqlcmd exe E i C joe db scripts joe db tasks Install sql 我需要添加特定的非标准端口 32001 我该怎么做 我在想一些像这样的标志 p或其他东西 但我不知道语法 根据这
  • 在select语句中显示表名

    我需要在 select 语句中显示表名 如何 确切的问题 我们在两个表中有公共列 我们正在使用以下方式显示记录 select column name from table name 1 union select column name fr
  • 如何使用 Google CardBoard Android SDK 和 Rajawali 制作一个简单的 VR 视频播放器

    我是这些领域的新人 我正在尝试改变一个program https github com ejeinc RajawaliCardboardExample现在在 github 中播放 Cardboard 视频 我使用 StreamingText
  • 为什么媒体查询的顺序在 CSS 中很重要?

    最近 我一直在设计响应速度更快的网站 并且经常使用 CSS 媒体查询 我注意到的一种模式是 定义媒体查询的顺序实际上很重要 我没有在每个浏览器中测试它 只是在 Chrome 上测试 这种行为有解释吗 有时 当您的网站无法正常工作并且您不确定
  • 数组中出现 NullPointerException

    我不断收到 NullPointerException 见下文 在 C 中一切正常 但在 android 中却崩溃了 arrDBNumbers 已满 代码应该运行并计算 1 2 3 等到 49 的数量 将 1 添加到 arrFreq i 1
  • Python - Flask:找不到 render_template() [重复]

    这个问题在这里已经有答案了 我是烧瓶新手 我有这个代码 你能给我一个建议吗 我做错了什么 谢谢 from flask import Flask from flask import request from flask import rend
  • Android:2个具有相同包的aar库

    Edit 基于此讨论的后续问题已发布在以下链接中 Android 如何管理同一应用程序使用的多个库中的公共代码库 https stackoverflow com questions 57572278 android how to manag
  • 我无法更改 static void Main(string[] args)

    我无法在控制台应用程序中更改 static void Main string args 谁能告诉我如何将其更改为其他内容 如果您的意思是无法将其更改为非静态的 或者无法更改其名称 那就对了 应用程序的入口点 must叫做Main must保
  • ASP.NET 部分回发期间打开时的 jQueryUI 日期选择器行为:年份变为 1899 或 1900

    我在 jQueryUI 日期选择器和 UpdatePanel 中遇到了一个非常有趣的错误 其中日期选择器选择的日期大约是 100 年后 jQuery 的版本为 1 6 2 jQueryUI 的版本为 1 8 14 这是粗略的布局
  • 了解事件循环

    我正在思考这个问题 这就是我想到的 我们看下面这段代码 console clear console log a setTimeout function console log b 1000 console log c setTimeout