Javascript 什么';它是一个事件循环,与使用其他模型有什么不同?

Javascript 什么';它是一个事件循环,与使用其他模型有什么不同?,javascript,functional-programming,parallel-processing,node.js,Javascript,Functional Programming,Parallel Processing,Node.js,我一直在研究Node.JS,所有的文档和博客都在讨论它如何使用事件循环而不是每个请求模型 我在理解差异时有些困惑。我觉得我已经80%理解了它,但还没有完全理解它。将传入的请求或回调视为事件,它们被排队处理 这与大多数GUI系统中所做的完全相同。系统无法知道用户何时会单击按钮或进行一些交互。但当他这样做时,事件将传播到事件循环,该循环基本上是一个检查队列中的新事件并对其进行处理的循环 优点是,你不必为自己等待结果。而是注册在触发事件时执行的回调函数。这使得框架能够处理I/O内容,在处理长时间的操作

我一直在研究Node.JS,所有的文档和博客都在讨论它如何使用事件循环而不是每个请求模型


我在理解差异时有些困惑。我觉得我已经80%理解了它,但还没有完全理解它。

将传入的请求或回调视为事件,它们被排队处理

这与大多数GUI系统中所做的完全相同。系统无法知道用户何时会单击按钮或进行一些交互。但当他这样做时,事件将传播到事件循环,该循环基本上是一个检查队列中的新事件并对其进行处理的循环

优点是,你不必为自己等待结果。而是注册在触发事件时执行的回调函数。这使得框架能够处理I/O内容,在处理长时间的操作时,您可以轻松地依赖它的内部效率,而不是自己阻塞流程


简而言之,除了您的代码之外,所有东西都是并行运行的。永远不会有两个回调函数片段同时运行–事件循环是单个线程。但是,在外部执行stuff并最终传播事件的进程可以分布在多个线程/进程中。

线程模型将为每个请求生成一个新线程。这意味着您将在计算和内存方面获得相当大的开销。事件循环在单个线程中运行,这意味着您不会得到开销

这样做的结果是您必须更改您的编程模型。因为所有这些不同的事情都发生在同一个线程中,所以不能阻止。这意味着您不能等待某些事情发生,因为这会阻塞整个线程。相反,您定义了一个回调,该回调在操作完成后调用。这通常称为非阻塞I/O

阻塞I/O的伪示例:

row = db_query('SELECT * FROM some_table');
print(row);
db_query('SELECT * FROM some_table', function (row) {
  print(row);
});
非阻塞I/O的伪示例:

row = db_query('SELECT * FROM some_table');
print(row);
db_query('SELECT * FROM some_table', function (row) {
  print(row);
});
这个例子使用lambdas(匿名函数),就像它们一直在JavaScript中使用一样。JS大量使用事件,这正是回调的意义所在。操作完成后,将触发触发回调的事件。这就是为什么它通常被称为事件模型异步模型

该模型的实现使用一个循环来处理和触发这些事件。这就是为什么它被称为事件队列事件循环

事件队列框架的突出示例包括:

  • (红宝石)
  • (Python)
  • (V8服务器端JavaScript)

事件循环允许您处理与硬盘或网络通话所需的时间。用下面列出的时间:

Source | CPU Cycles
L1     | 3 Cycles
L2     | 14 Cycles
RAM    | 250  Cycles
Disk   | 41,000,000 Cycles
Network| 240,000,000 Cycles

在PHP中运行curl只会浪费CPU。

也许可以更具体地说明您不了解的内容?我认为重要的是要说明事件队列并不意味着没有线程池。例如,node.js大量使用线程池在内部阻塞操作。事件队列模型的核心是如何与这些长时间执行的操作进行交互。“在外部执行内容并最终传播事件的进程可以分布在多个线程/进程中。”这是否也适用于vanilla JS引擎(即非节点)?因为我自己也在想同样的事情。。。事件传播和外部请求必须由单独的线程处理,即使执行实际JS代码的线程只有一个。但是我读到的每一篇文章都说,即使是JS引擎也是单线程的,这让我难以置信。