简体   繁体   English

为什么node.js是异步的?

[英]Why is node.js asynchronous?

Nobody has actually asked this (from all the 'suggestions' I'm getting and also from searching before I asked here). 实际上没有人问过这个问题(来自我提出的所有'建议'以及我在此之前提到的搜索)。

So why is node.js asynchronous? 那么为什么node.js是异步的呢?

From what I have deduced after some research: 根据我在一些研究后得出的结论:

Languages like PHP and Python are scripting languages (I could be wrong about the actual languages that are scripting languages) whilst JavaScript isn't. 像PHP和Python这样的语言是脚本语言(我可能错误的是脚本语言的实际语言),而JavaScript则不然。 (I suppose this derives from the fact that JS doesn't compile?) (我想这源于JS不编译的事实?)

Node.js runs on a single thread whilst scripting languages use multiple threads. Node.js在单个线程上运行,而脚本语言使用多个线程。

Asynchronous means stateless and that the connection is persistent whilst synchronous is the (almost) opposite. 异步意味着无状态,并且连接是持久的,而同步是(几乎)相反的。

Maybe the answer is found somewhere stated above, but I'm still not sure. 也许答案是在上面所说的地方找到的,但我仍然不确定。

My second and last question related to this topic is this: 我与本主题相关的第二个也是最后一个问题是:

Could JavaScript be made into a synchronous language? JavaScript可以成为同步语言吗?

PS. PS。 I know some of you will ask "why would you want to make JS synchronous?" 我知道有些人会问“你为什么要让JS同步?” in your answers, but the truth is that I don't. 在你的答案中,但事实是我没有。 I'm just asking these types of questions because I'm sure there are more people out there than just myself that have thought about such questions. 我只是问这些类型的问题,因为我确信那里有更多的人,而不仅仅是我自己想过这些问题。

Node.js runs on a single thread whilst scripting languages use multiple threads. Node.js在单个线程上运行,而脚本语言使用多个线程。

Not technically. 不是技术上的。 Node.js uses several threads, but only one execution thread. Node.js使用多个线程,但只使用一个执行线程。 The background threads are for dealing with IO to make all of the asynchronous goodness work. 后台线程用于处理IO以使所有异步良好工作。 Dealing with threads efficiently is a royal pain, so the next best option is to run in an event loop so code can run while background threads are blocked on IO. 有效处理线程是一种巨大的痛苦,因此下一个最佳选择是在事件循环中运行,以便在IO上阻止后台线程时运行代码。

Asynchronous means stateless and that the connection is persistent whilst synchronous is the (almost) opposite. 异步意味着无状态,并且连接是持久的,而同步是(几乎)相反的。

Not necessarily. 不必要。 You can preserve state in an asynchronous system pretty easily. 您可以非常轻松地在异步系统中保留状态。 For example, in Javascript, you can use bind() to bind a this to a function, thereby preserving state explicitly when the function returns: 例如,在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 () {
};

Asynchronous means not waiting for an operation to finish, but registering a listener instead. 异步意味着不等待操作完成,而是注册一个监听器。 This happens all the time in other languages, notably anything that needs to accept input from the user. 这种情况一直发生在其他语言中,特别是需要接受用户输入的任何事情。 For example, in a Java GUI, you don't block waiting for the user to press a button, but you register a listener with the GUI. 例如,在Java GUI中,您不会阻止等待用户按下按钮,而是使用GUI注册侦听器。

My second and last question related to this topic is this: 我与本主题相关的第二个也是最后一个问题是:

Could JavaScript be made into a synchronous language? JavaScript可以成为同步语言吗?

Technically, all languages are synchronous, even Javascript. 从技术上讲,所有语言都是同步的,甚至是Javascript。 However, Javascript works a lot better in an asynchronous design because it was designed to be single threaded. 但是,Javascript在异步设计中工作得更好,因为它被设计为单线程。

Basically there are two types of programs: 基本上有两种类型的程序:

  • CPU bound- the only way to make it go faster is to get more CPU time CPU绑定 - 使其更快的唯一方法是获得更多的CPU时间
  • IO bound- spends a lot of time waiting for data, so a faster processor won't matter IO界限 - 花费大量时间等待数据,因此更快的处理器无关紧要

Video games, number crunchers and compilers are CPU bound, whereas web servers and GUIs are generally IO bound. 视频游戏,数字计算器和编译器受CPU限制,而Web服务器和GUI通常是IO绑定的。 Javascript is relatively slow (because of how complex it is), so it wouldn't be able to compete in a CPU bound scenario (trust me, I've written my fair share of CPU-bound Javascript). Javascript相对较慢(因为它有多复杂),所以它无法在CPU绑定场景中竞争(相信我,我已经写了我公平分享的CPU绑定Javascript)。

Instead of coding in terms of classes and objects, Javascript lends itself to coding in terms of simple functions that can be strung together. Javascript不仅可以根据类和对象进行编码,而且可以根据可以串联在一起的简单函数进行编码。 This works very well in asynchronous design, because algorithms can be written to process data incrementally as it comes in. IO (especially network IO) is very slow, so there's quite a bit of time between packets of data. 这在异步设计中非常有效,因为可以编写算法来逐步处理数据.IO(特别是网络IO)非常慢,因此数据包之间有相当长的时间。

Example

Let's suppose you have 1000 live connections, each delivering a packet every millisecond, and processing each packet takes 1 microsecond (very reasonable). 假设您有1000个实时连接,每个连接每毫秒提供一个数据包,处理每个数据包需要1微秒(非常合理)。 Let's also assume each connection sends 5 packets. 我们还假设每个连接发送5个数据包。

In a single-threaded, synchronous application, each connection will be handled in series. 在单线程同步应用程序中,每个连接都将按顺序处理。 The total time taken is (5*1 + 5*.001) * 1000 milliseconds, or ~5005 milliseconds. 所花费的总时间是(5 * 1 + 5 * .001)* 1000毫秒,或~5005毫秒。

In a single-threaded, asynchronous application, each connection will be handled in parallel. 在单线程异步应用程序中,每个连接将并行处理。 Since every packet takes 1 millisecond, and processing each packet takes .001 milliseconds, we can process every connection's packet between packets, so our formula becomes: 1000*.001 + 5*1 milliseconds, or ~6 milliseconds. 由于每个数据包需要1毫秒,处理每个数据包需要0.001毫秒,我们可以处理数据包之间的每个连接数据包,因此我们的公式变为:1000 * .001 + 5 * 1毫秒,或~6毫秒。

The traditional solution to this problem was to create more threads. 解决此问题的传统方法是创建更多线程。 This solved the IO problem, but then when the number of connections rose, so did the memory usage (threads cost lots of memory) and CPU usage (multiplexing 100 threads onto 1 core is harder than 1 thread on 1 core). 这解决了IO问题,但是当连接数量增加时,内存使用量(线程占用大量内存)和CPU使用率(将100个线程复用到1个核心比1个核心上的1个线程更难)。

However, there are downsides. 但是,有缺点。 If your web application happens to also need to do some heavy number crunching, you're SOL because while you're crunching numbers, connections need to wait. 如果您的Web应用程序碰巧也需要进行大量的数字运算,那么您就是SOL,因为当您处理数字时,连接需要等待。 Threading solves this because the OS can swap out your CPU-intensive task when data is ready for a thread waiting on IO. 线程解决了这个问题,因为当数据准备好等待IO的线程时,操作系统可以交换CPU密集型任务。 Also, node.js is bound to a single core, so you can't take advantage of your multi-core processor unless you spin up multiple instances and proxy requests. 此外,node.js绑定到单个核心,因此除非您启动多个实例和代理请求,否则无法利用多核处理器。

Javascript does not compile into anything. Javascript不会编译成任何东西。 It's "evaluated" at runtime, just like PHP & Ruby. 它在运行时被“评估”,就像PHP和Ruby一样。 Therefore it is a scripting language just like PHP/Ruby. 因此它就像PHP / Ruby一样是一种脚本语言。 (it's official name is actually ECMAScript). (它的官方名称实际上是ECMAScript)。

The 'model' that Node adheres to is a bit different than PHP/Ruby. Node遵循的“模型”与PHP / Ruby略有不同。 Node.js uses an 'event loop' (the single thread) that has the one goal of taking network requests and handling them very quickly, and if for any reason it encounters an operation that takes a while (API request, database query -- basically anything involving IO (input/output)) it passes that off to a background 'worker' thread and goes off to do something else while the worker thread waits for the long task to complete. Node.js使用“事件循环”(单个线程),其目标是获取网络请求并快速处理它们,并且如果由于任何原因它遇到需要一段时间的操作(API请求,数据库查询 - 基本上任何涉及IO(输入/输出)的东西都会将其传递给后台“工作者”线程,并在工作线程等待长任务完成时继续执行其他操作。 When that happens the main 'event loop' will take the results and continue deal with them. 当发生这种情况时,主“事件循环”将获取结果并继续处理它们。

PHP/Ruby following a threading model. PHP / Ruby遵循线程模型。 Essentially, for every incoming network request, the application server spins up an isloated thread or process to handle the request. 实质上,对于每个传入的网络请求,应用程序服务器都会旋转一个isloated线程或进程来处理请求。 This does not scale tremendously well and Node's approach is cited as one of its core strengths compared to this model. 这种方法的扩展性不是很好,与此模型相比,Node的方法被认为是其核心优势之一。

Asynchronous means stateless and that the connection is persistent whilst synchronous is the (almost) opposite. 异步意味着无状态,并且连接是持久的,而同步是(几乎)相反的。

No. Synchronous instructions are completed in a natural order, from first to last. 否。同步指令按照自然顺序完成,从头到尾。 Asynchronous instructions mean that if a step in the flow of a program takes a relatively long time, the program will continue executing operations and simply return to this operation when complete. 异步指令意味着如果程序流程中的一个步骤需要相对较长的时间,程序将继续执行操作,并在完成时简单地返回此操作。

Could JavaScript be made into a synchronous language? JavaScript可以成为同步语言吗?

Certain operations in JavaScript are synchronous. JavaScript中的某些操作是同步的。 Others are asynchronous. 其他人是异步的。 For example: 例如:


Blocking operations: 阻止操作:

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');

Asynchronous: 异步:

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.');

Could JavaScript be made into a synchronous language? JavaScript可以成为同步语言吗?

Javascript is not an "asynchronous language"; Javascript不是“异步语言”; rather, node.js has a lot of asynchronous APIs . 相反, node.js有很多异步API Asynchronous-ness is a property of the API and not the language. Asynchronous-ness是API的属性,而不是语言。 The ease with which functions can be created and passed around in javascript makes it convenient to pass callback functions, which is one way to handle control flow in an asynchronous API, but there's nothing inherently asynchronous about javascript . 可以在javascript中轻松创建和传递函数,这使得传递回调函数变得很方便,这是处理异步API中控制流的一种方法,但javascript没有任何本质上的异步。 Javascript can easily support synchronous APIs. Javascript可以轻松支持同步API。

Why is node.js asynchronous? 为什么node.js是异步的?

Node.js favors asynchronous APIs because it is single-threaded. Node.js支持异步API,因为它是单线程的。 This allows it to efficiently manage its own resources, but requires that long-running operations be non-blocking, and asynchronous APIs are a way to allow for control of flow with lots of non-blocking operations. 这允许它有效地管理自己的资源,但要求长时间运行的操作是非阻塞的,异步API是一种允许通过大量非阻塞操作来控制流的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM