为什么 node.js 是异步的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17607280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is node.js asynchronous?
提问by Joe
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. (I suppose this derives from the fact that JS doesn't compile?)
像 PHP 和 Python 这样的语言是脚本语言(我可能对脚本语言的实际语言有误)而 JavaScript 不是。(我想这是因为 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. I know some of you will ask "why would you want to make JS synchronous?" 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.
附注。我知道你们中的一些人会问“为什么要使 JS 同步?” 在你的答案中,但事实是我没有。我只是问这些类型的问题,因为我确信除了我自己之外,还有更多人考虑过这些问题。
回答by beatgammit
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. The background threads are for dealing with IO to make all of the asynchronous goodness work. 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.
技术上不是。Node.js 使用多个线程,但只有一个执行线程。后台线程用于处理 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 thisto a function, thereby preserving state explicitly when the function returns:
不必要。您可以非常轻松地在异步系统中保留状态。例如,在 Javascript 中,您可以使用bind()将 a 绑定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. However, Javascript works a lot better in an asynchronous design because it was designed to be single threaded.
从技术上讲,所有语言都是同步的,甚至 Javascript。然而,Javascript 在异步设计中工作得更好,因为它被设计为单线程。
Basically there are two types of programs:
基本上有两种类型的程序:
- CPU bound- the only way to make it go faster is to get more CPU time
- IO bound- spends a lot of time waiting for data, so a faster processor won't matter
- CPU 受限——让它运行得更快的唯一方法是获得更多的 CPU 时间
- IO 限制- 花费大量时间等待数据,因此更快的处理器无关紧要
Video games, number crunchers and compilers are CPU bound, whereas web servers and GUIs are generally IO bound. 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).
视频游戏、数字处理器和编译器受 CPU 限制,而 Web 服务器和 GUI 通常受 IO 限制。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. 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.
Javascript 不是根据类和对象进行编码,而是根据可以串在一起的简单函数进行编码。这在异步设计中非常有效,因为可以编写算法以在数据传入时以增量方式处理数据。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). Let's also assume each connection sends 5 packets.
假设您有 1000 个实时连接,每个连接每毫秒传送一个数据包,处理每个数据包需要 1 微秒(非常合理)。我们还假设每个连接发送 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. Threading solves this because the OS can swap out your CPU-intensive task when data is ready for a thread waiting on IO. 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.
但是,也有缺点。如果您的 Web 应用程序碰巧还需要进行一些繁重的数字运算,那么您就是 SOL,因为在处理数字时,连接需要等待。线程解决了这个问题,因为当数据准备好等待 IO 的线程时,操作系统可以换出 CPU 密集型任务。此外,node.js 绑定到单核,因此除非您启动多个实例和代理请求,否则您无法利用多核处理器。
回答by Casey Flynn
Javascript does not compile into anything. It's "evaluated" at runtime, just like PHP & Ruby. Therefore it is a scripting language just like PHP/Ruby. (it's official name is actually ECMAScript).
Javascript 不会编译成任何东西。它在运行时被“评估”,就像 PHP 和 Ruby 一样。因此,它是一种类似于 PHP/Ruby 的脚本语言。(它的正式名称实际上是 ECMAScript)。
The 'model' that Node adheres to is a bit different than 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 I.O. (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. When that happens the main 'event loop' will take the results and continue deal with them.
Node 遵循的“模型”与 PHP/Ruby 有点不同。Node.js 使用一个“事件循环”(单线程),它的一个目标是接收网络请求并非常快速地处理它们,如果由于任何原因它遇到一个需要一段时间的操作(API 请求、数据库查询——基本上任何涉及 IO(输入/输出)的东西)它将它传递给后台“工作”线程,并在工作线程等待长任务完成时开始做其他事情。当这种情况发生时,主要的“事件循环”将获取结果并继续处理它们。
PHP/Ruby following a threading model. Essentially, for every incoming network request, the application server spins up an isloated thread or process to handle the request. This does not scale tremendously well and Node's approach is cited as one of its core strengths compared to this model.
PHP/Ruby 遵循线程模型。本质上,对于每个传入的网络请求,应用程序服务器都会启动一个孤立的线程或进程来处理请求。这不能很好地扩展,与此模型相比,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. Others are asynchronous. For example:
JavaScript 中的某些操作是同步的。其他是异步的。例如:
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.');
回答by Trevor Dixon
Could JavaScript be made into a synchronous language?
JavaScript 能否成为同步语言?
Javascript is not an "asynchronous language"; rather, node.jshas a lot of asynchronous APIs. Asynchronous-ness is a property of the API and not the language. 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 can easily support synchronous APIs.
Javascript 不是“异步语言”;相反,node.js有很多异步API。异步性是 API 的属性,而不是语言的属性。在 javascript 中可以轻松创建和传递函数,这使得传递回调函数变得很方便,这是在异步 API 中处理控制流的一种方式,但是javascript没有任何本质上的异步。Javascript 可以轻松支持同步 API。
Why is node.js asynchronous?
为什么 node.js 是异步的?
Node.js favors asynchronous APIs because it is single-threaded. 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.
Node.js 偏爱异步 API,因为它是单线程的。这允许它有效地管理自己的资源,但要求长时间运行的操作是非阻塞的,异步 API 是一种允许通过大量非阻塞操作控制流的方法。

