javascript-为什么node.js是异步的?

实际上,没有人问过这个问题(从我得到的所有“建议”以及在我问这里之前的搜索中)。

那么为什么node.js是异步的呢?

经过一些研究,我得出的结论是:

诸如PHP和Python之类的语言是脚本语言(对于脚本语言而言,我可能是错的),而JavaScript并非如此。 (我想这是因为JS无法编译的事实?)

Node.js在单个线程上运行,而脚本语言使用多个线程。

异步意味着无状态,并且连接是持久的,而同步是(几乎)相反的。

也许答案在上面提到的某个地方,但是我仍然不确定。

我与此主题相关的第二个也是最后一个问题是:

可以将JavaScript制成同步语言吗?

PS。 我知道有些人会问“为什么要使JS同步?” 在您的回答中,但事实是我没有。 我只是问这些类型的问题,因为我敢肯定有更多的人在思考这样的问题,而不仅仅是我自己。

3个解决方案
54 votes

Node.js在单个线程上运行,而脚本语言使用多个线程。

从技术上来说不是。 Node.js使用多个线程,但仅使用一个执行线程。 后台线程用于处理IO,以使所有异步优势发挥作用。 有效地处理线程是一种皇家痛苦,因此,下一个最佳选择是在事件循环中运行,以便在后台线程在IO上被阻止的同时运行代码。

异步意味着无状态,并且连接是持久的,而同步是(几乎)相反的。

不必要。 您可以非常轻松地在异步系统中保存状态。 例如,在Javascript中,可以使用bind()this绑定到函数,从而在函数返回时显式保留状态:

function State() {
    // make sure that whenever doStuff is called it maintains its state
    this.doStuff = this.doStuff.bind(this);
}
State.prototype.doStuff = function () {
};

异步意味着不等待操作完成,而是注册一个侦听器。 这种情况一直以其他语言出现,尤其是需要接受用户输入的任何语言。 例如,在Java GUI中,您不会阻止等待用户按下按钮,而是在GUI中注册了侦听器。

我与此主题相关的第二个也是最后一个问题是:

可以将JavaScript制成同步语言吗?

从技术上讲,所有语言都是同步的,甚至是Javascript。 但是,由于Javascript是单线程设计的,因此在异步设计中的效果要好得多。

基本上有两种类型的程序:

  • CPU限制-使它运行更快的唯一方法是获得更多的CPU时间
  • IO受限-花费大量时间等待数据,因此更快的处理器将无关紧要

视频游戏,数字处理器和编译器受CPU限制,而Web服务器和GUI通常受IO限制。 Javascript相对较慢(由于它的复杂性),因此它无法在CPU受限的情况下竞争(相信我,我写了相当一部分CPU受限的Javascript)。

Javascript不用根据类和对象进行编码,而是根据可以组合在一起的简单函数进行编码。 这在异步设计中非常有效,因为可以编写算法来逐步处理传入的数据。IO(尤其是网络IO)非常慢,因此数据包之间有相当长的时间。

假设您有1000个活动连接,每个连接每毫秒发送一个数据包,并且处理每个数据包需要1微秒(非常合理)。 我们还假设每个连接发送5个数据包。

在单线程同步应用程序中,每个连接将按顺序处理。 总耗时为(5 * 1 + 5 * .001)* 1000毫秒,或〜5005毫秒。

在单线程异步应用程序中,每个连接将并行处理。 由于每个数据包花费1毫秒,处理每个数据包花费.001毫秒,因此我们可以处理数据包之间的每个连接的数据包,因此我们的公式变为:1000 * .001 + 5 * 1毫秒,即〜6毫秒。

解决此问题的传统方法是创建更多线程。 这解决了IO问题,但是当连接数量增加时,内存使用率(线程会消耗大量内存)和CPU使用率(CPU占用率也提高了)(将100个线程复用到1个内核上要比1个内核上的1个线程难)。

但是,还有缺点。 如果您的Web应用程序恰好也需要进行大量的数字运算,那么您就是SOL,因为在处理数字时,连接需要等待。 线程解决了这个问题,因为当数据准备好等待IO的线程时,操作系统可以换出您的CPU密集型任务。 而且,node.js绑定到单个内核,因此除非您启动多个实例和代理请求,否则您无法利用多核处理器。

beatgammit answered 2020-02-29T08:50:17Z
32 votes

Javascript不会编译成任何东西。 就像PHP和Ruby一样,它在运行时被“评估”。 因此,它是一种脚本语言,就像PHP / Ruby。 (它的正式名称实际上是ECMAScript)。

Node遵循的“模型”与PHP / Ruby有所不同。 Node.js使用一个“事件循环”(单线程),其目标是快速处理网络请求并快速处理它们,并且如果出于某种原因,它遇到需要花费一段时间的操作(API请求,数据库查询- 基本上所有涉及IO(输入/输出)的事物都将其传递给后台“工作者”线程,然后在工作者线程等待较长的任务完成时又去做其他事情。 当发生这种情况时,主“事件循环”将获取结果并继续处理。

PHP / Ruby遵循线程模型。 本质上,对于每个传入的网络请求,应用服务器都会启动一个独立的线程或进程来处理该请求。 与这种模型相比,这不能很好地扩展,Node的方法被认为是其核心优势之一。

异步意味着无状态,并且连接是持久的   而同步是(几乎)相反的。

不会。同步指令从头到尾都是自然顺序完成的。 异步指令意味着,如果程序流程中的某个步骤花费了相对较长的时间,则该程序将继续执行操作,并在完成后简单地返回该操作。

可以将JavaScript制成同步语言吗?

JavaScript中的某些操作是同步的。 其他是异步的。例如:


阻止操作:

for(var k = 0; k < 1; k = k - 1;){
  alert('this will quickly get annoying and the loop will block execution')
alert('this is blocked and will never happen because the above loop is infinite');

异步:

jQuery.get('/foo', function (result) { alert('This will occur 2nd, asynchronously'); });
alert('This will occur 1st. The above operation was skipped over and execution continued until the above operation completes.');
Casey Flynn answered 2020-02-29T08:51:14Z
20 votes

可以将JavaScript制成同步语言吗?

Javascript不是“异步语言”; 相反,node.js具有许多异步API。 异步性是API的属性,而不是语言的属性。 可以轻松地在javascript中创建和传递函数,这使得传递回调函数变得很方便,这是处理异步API中的控制流的一种方法,但是javascript本质上不是异步的。 Javascript可以轻松支持同步API。

为什么node.js是异步的?

Node.js支持异步API,因为它是单线程的。 这使它可以有效地管理自己的资源,但是要求长时间运行的操作必须是非阻塞的,并且异步API是一种允许使用大量非阻塞操作来控制流的方法。

Trevor Dixon answered 2020-02-29T08:51:49Z
translate from https://stackoverflow.com:/questions/17607280/why-is-node-js-asynchronous