什么是Node?(What's node) (译)

================================================================================
什么是Node?(What’s node)
http://jayli.github.io/whatisnode/index.html
作者:Brett McLaughlin 翻译: DAMAGAO
================================================================================
Node 不是万能药!但的确能解决一些关键问题。
学习 Node 不是一件轻松事儿,但你所收到的回报是对得起你的付出的。
因为当下 Web 应用开发中的诸多难题唯有 JavaScript 才能解决。

——————————————————————————–
目录
.专家们的警告!
.Node:几个小例子
.Node 不是 JavaScript,Node 可以运行 JavaScript
.和 Node 服务器的交互
.快速入门手册
.解释器之惑
.基于事件的 Web 应用
.Node 的用武之地

Node.js. It’s the latest in a long line of “Are you cool enough to use me?” programming languages, APIs, and toolkits. In that sense, it lands squarely in the tradition of Rails, and Ajax, and Hadoop, and even to some degree iPhone programming and HTML5. Go to a big technical conference, and you’ll almost certainly find a few talks on Node.js, although most will fly far over the head of the common mortal programmer.
对于 Node.js 用一句话俩说“你够酷吗?来用我吧!”,可见 Node.js 为最新潮的编程语言, 提供了一系列 API和工具集。在一些场景,它可以直接应用于传统的 Rails、Ajax、Hadoop、甚至可以某种程度上用于 iPhone 和 HTML5 开发。如果你参加过一些大型技术会议,你总是会听到一些关于 Node.js 的主题演讲,尽管大部分话题对普通的开发者来说遥不可及。

Dig a little deeper, and you’ll hear that Node.js (or, as it’s more briefly called by many, simply “Node”) is a server-side solution for JavaScript, and in particular, for receiving and responding to HTTP requests. If that doesn’t completely boggle your mind, by the time the conversation heats up with discussion of ports, sockets, and threads, you’ll tend to glaze over. Is this really JavaScript? In fact, why in the world would anyone want to run JavaScript outside of a browser, let alone the server?
稍微深入一点,你将知道 Node.js(常常我们将其简称为“ Node”)是一个为 JavaScript 的服务器端的解决方案,特别是用来接受和相应 HTTP 请求。如果这还没有震惊你的脑袋,通过关于端口、sockets 和线程的讨论可以震惊你了,你会觉得这些东西让你眼花缭乱。这真的是 JavaScript 的范畴吗?事实上,为什么世界上那么多人宁愿将 JavaScript 脱离浏览器来运行,更不用说将 JavaScript 作为服务器了?

The good news is that you’re hearing (and thinking) about the right things. Node really is concerned with network programming and server-side request/response processing. The bad news is that like Rails, Ajax, and Hadoop before it, there’s precious little clear information available. There will be, in time — as there now is for these other “cool” frameworks that have matured — but why wait for a book or tutorial when you might be able to use Node today, and dramatically improve the maintainability of your code and even the ease with which you bring on programmers?
好消息是,你所听到的(所想到的)关于 Node 的一切都是事实。Node 的确是属于网络编程的范畴,用以服务器端的请求和响应处理。坏消息是和之前的 Rails、Ajax 和 Hadoop 一样,真正有用的资料实在太少。当一些“优秀的”框架成熟时, 到时这些都会有的,但何必要等到技术书籍和教程都出来之后再去尝试使用 Node 呢?现在就使用 Node,可以极大提高你的代码的维护,甚至让你的程序变得更易。

——————————————————————————–
一、A warning to the Node experts out there
一、Node 专家门的警告!
Node is like most technologies that are new to the masses, but old hat to the experienced few: it’s opaque and weird to most but completely usable for a small group. The result is that if you’ve never worked with Node, you’re going to need to start with some pretty basic server-side scripts. Take your time making sure you know what’s going on, because while this is JavaScript, it’s not operating like the client-side JavaScript you’re used to. In fact, you’re going to have to twist your JavaScript brain around event loops and waiting and even a bit of network theory.
Node 和大多数技术一样,对于一般人来看新的,对于少数有专家来看是老的:对于大多数人,Node 来机看起不透明又很怪异,但对于小的开发团队很受亲睐。这导致,如果你从来没有接触过 Node,则只需要从一些很容易上手的服务器端脚本开始。你需要花时间来搞清楚运行什么,因为即便是 JavaScript,该 JavaScript 和客户端 JavaScript 也极为不同。实际情况是,你必须转动你的 JavaScript 脑袋,理解事件循环、等待 和一些网络基础知识。

Unfortunately, this means that if you’ve been working and playing with Node for a year or two, much of this article is going to seem pedestrian and overly simplistic. You’ll look for things like using Node on the client, or heavy theory discussions on evented I/O and reactor patterns, and npm. The reality is that while that’s all interesting — and advances Node to some pretty epic status — it’s incomprehensible to someone just getting started out. Given that, maybe you should pass this piece on to your co-workers who don’t know Node, and then when they’re buying into Node’s usefulness, start to bring them along on the more advanced Node use cases.
不幸的是,这意味着如果你已经用 Node 作开发超过两年时间的话,你会觉得这篇文章内容很单调乏而且过于简单。你会开始寻找新的“刺激”,比如将 Node 运行于客户端,或者关于事件 I/O 和反射模式的纯理论讨论、还有 npm 工具。你会发现 Node 的世界是如此有趣,甚至很多 Node 高级技术具有某种史诗般的美感,而这些东西对于初学者来说依然是难于企及的。因此,或许你应该将这篇文章分享给那些不知道 Node 的同事,当他们开始对 Node 感兴趣时,给他们分享 Node 高级技术。

——————————————————————————–
二、Node: A few basic examples
二、Node:几个小例子
First things first: you need to realize that Node is intended to be used for running standalone JavaScript programs. This isn’t a file referenced by a piece of HTML and running in a browser. It’s a file sitting on a file system, executed by the Node program, running as what amounts to a daemon, listening on a particular port.
首先,你应当意识到 Node 是用于运行独立的 JavaScript 程序的,而不是运行于浏览器中的某个 HTML 片段里。它是存放在文件系统中的真实存在的文件,它被 Node 程序执行,以一种守护进程的模式运行,同时监听某个端口。

Skipping hello world
跳过 hello world

The classic example here is “Hello World,” detailed on the Node website. Almost everyone starts with Hello World, though, so check that out on your own, and skip straight to something a lot more interesting: a server that can send static files, not just a single line of text:
最经典的例子当然是“Hello World“,在 Node 官网(http://nodejs.org/docs/latest )上有源码。几乎每个人都是从 Hello World 开始接触 Node 的,因此你自己学习,现在我们直接跳过更有趣的例子:发送静态文件的一个服务器,而不仅仅是发送一段文本到客户端。

var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, response) {
    var uri = url.parse(request.url).pathname;
    var filename = path.join(process.cwd(), uri);
    fs.exists(filename, function(exists) {
        if(!exists) {
            response.writeHead(404, {"Content-Type": "text/plain"});
            response.end("404 Not Found\n");
            return;
        }
        fs.readFile(filename, "binary", function(err, file) {
            if(err) {
                response.writeHead(500, {"Content-Type": "text/plain"});
                response.end(err + "\n");
                return;
            }
            response.writeHead(200);
            response.end(file, "binary");
        });
    });
}).listen(8080);
console.log("Server running at http://localhost:8080/");

Thanks much to Mike Amundsen for the pointer to similar code. This particular example was posted by Devon Govett on the Nettuts+ training blog, although it’s been updated for the current version of Node in a number of places. Devon’s entire tutorial post is actually a great companion piece on getting up to speed on Node once you have a handle on the basics.
感谢 Mike Amundsen,他给出了这段代码的相似的实现。这个例子是由 Devon Govett 在 Nettuts+ 上提交的一段代码,尽管已经根据新版本的 Node 作了更新。一旦你有了基础知识,之后 Devon 的整个教程对于迅速学习 Node 是一个非常好姊妹篇。

If you’re new to Node, type this code into a text file and save the file as NodeFileServer.js. Then head out to the Node website and download Node or check it out from the git repository. You’ll need to build the code from source; if you’re new to Unix, make, and configure, then check out the online build instructions for help.
如果你是一个 Node 的新手,你可以将上述代码保存到一个文本文件中,命名为 NodeFileServer.js。然后访问 Node 网站,且下载 Node, 或者到 github 上将源码取下来。你将需要编译源码,如果你没有用过 Unix、 make 和 configure ,则需要查阅在线编译手册来寻求帮助。

——————————————————————————–
三、Node runs JavaScript, but isn’t JavaScript
三、Node 不是 JavaScript,Node 可以运行JavaScript
Don’t worry that you’ve put aside NodeFileServer.js for a moment; you’ll come back to it and more JavaScript shortly. For now, soak in the realization that you’ve just run through the classic Unix configuration and build process:
不用担心,我们先抛开 NodeFileServer.js 一会儿,我们将等下会回过头来运行它的及更多 JavaScript。现在,让我们移步到现实当中来,在 Unix 中执行典型的配置和编译命令:

./configure
make
make install

That should come with another realization: Node itself isn’t JavaScript. Node is a program for running JavaScript, but isn’t JavaScript itself. In fact, Node is a C program. Do a directory listing on the Node/src directory and you’ll see something like this:
这让我们确信一个事实:Node 不是 JavaScript,Node 是一个可以运行 JavaScript 的程序,但 Node 绝对不是 JavaScript。实际上,Node 是基于 C 写的程序。可以通过 ls 来查看 Node/src 目录中的文件,可以看到 Node 的源码:
这里写图片描述

For all of you thinking that JavaScript is a poor language in which to be writing server-side tools, you’re half right. Yes, JavaScript is not equipped to deal with operating system-level sockets and network connectivity. But Node isn’t written in JavaScript; it’s written in C, a language perfectly capable of doing the grunt work and heavy lifting required for networking. JavaScript is perfectly capable of sending instructions to a C program that can be carried out in the dungeons of your OS. In fact, JavaScript is far more accessible than C to most programmers — something worth noting now, and that will come up again and again in the reasons for looking seriously at Node.
大多数人会以为,JavaScript 是一门糟糕的语言,更不用说用它来实现服务器端的工具,其实你只对了一半。不错,对于操作系统级别的 Socket 和网络编程来说,JavaScript 可能并不能胜任。但 Node 并不是 JavaScript 实现的,它是基于 C 实现的。C 语言是可以完美的胜任任意量级的网络编程的。而 JavaScript 则完全有能力将指令传递给 C 程序,然后由 C 程序在操控操作系统层运行。实际上,和 C 语言相比,JavaScript 更容易被开发者们接触到,这是值得引起注意的地方,这就是看中 Node 而一再被提及的原因。

The primary usage of Node further reflects that while Node works with JavaScript, it isn’t itself JavaScript. You run it from the command line:
Node 的基本用法,进一步反映出了 Node 是如何和 JavaScript 一起工作的,Node 不是 JavaScript。你可以通过命令行来运行它:

— (bdm0509@Bretts-MacBook-Pro Sun, 29 May 11)
— — — — — — — — — — (/Users/bdm0509/tmp/Node/src) —
— (09:09 $)-> export PATH=$HOME/local/Node/bin:$PATH
— (bdm0509@Bretts-MacBook-Pro Sun, 29 May 11)
— — — — — — — — — — (/Users/bdm0509/tmp/Node/src) —
— (09:09 $)-> cd ~/examples
— (bdm0509@Bretts-MacBook-Pro Sun, 29 May 11)
— — — — — — — — — — — — (/Users/bdm0509/examples) —
— (09:09 $)-> Node NodeFileServer.js
Server running at http://127.0.0.1:8080/

And there you have it. While there’s a lot more to be said about that status line — and what’s really going on at port 8080 — the big news here is that Node is a program that you feed JavaScript. What Node then does with that JavaScript isn’t worth much ink; to some degree, just accept that what it does, it does. This frees you up to write JavaScript, not worry about learning C. Heck, a big appeal to Node is that you can actually write a server without worrying about C. That’s the point.
现在你肯定对 Node 有个大概的了解了吧。对于这段命令行,的确还有很多知识点需要进一步解释说明,– 比如在端口 8080 到底发生了什么? – 但这里你只需知道,Node 只是一个可以让你运行 JavaScript 的程序。读者不必纠结于 Node 如何和 JavaScript 协同工作,这里也不会对此做过多介绍,只要知道 Node 可以运行 JavaScript,这就足够了。而且你只需学习 JavaScript 这一门编程语言即可,不用担心自己不懂 C 语言。记住这是最最重要的一点,不必了解 C 也可写出 Node 可运行的程序。

——————————————————————————–
四、Interacting with a “Node server”
四、和 Node 服务器的交互
Make sure you still have your NodeFileServer.js code running via Node. Then you can hit your local machine — on port 8080 — and see this unremarkable output.
刚才我们在 Node 上运行了 NodeFileServer.js。这时你可以访问你本机的 8080 端口,可以看到正常的输出。
这里写图片描述

Yes, this is about as mundane as you can get. Well, that is, until you realize that you’ve actually written a file server in about 20 lines of code. The output you see — the actual code of the script you wrote — isn’t canned in the script itself. It’s being served from the file system. Throw an image into the same directory, and simply add the name of the image to the end of your URL, like http://localhost:8080/my_image.png:
没错,输出结果不足为奇。但应当意识到我们只用短短20行代码就实现了一个文件服务器。你看到的输出 – 你写脚本的实际代码 – 在这个脚本中代码没有被封装成二进制。这个文件服务器可以输出它上面的任何文件。如果在同样目录下放入一张图片,在 URL 后缀中写上图片文件名,就像这样:http://localhost:8080/my_image.png
这里写图片描述

Node happily serves this binary image up. That’s pretty remarkable, when you again refer to the brevity of the code. On top of that, how hard would it be if you wanted to write your own server code in JavaScript? Not only that, but suppose you wanted to write that code to handle multiple requests? (That’s a hint; open up four, five, or 10 browsers and hit the server.) The beauty of Node is that you can write entirely simple and mundane JavaScript to get these results.
Node 也可以展示出二进制的图片文件。当你回头再看这段短小的程序时,一定觉得这太不可思议了。最重要的是,如果你想使用 JavaScript 来编写自己的 server 代码, 要如何实现?不仅如此,假设你想写一个可以处理多个请求的代码呢?(一个提示,同时打开四个, 五个甚至十个浏览器,来访问该服务器)。Node 让人着迷的地方在于,你完全可以用很简单而且很不起眼的 JavaScript 程序来完成你想要的这些结果。

——————————————————————————–
五、A quick line-by-line primer
五、快速入门手册
There’s a lot more to talk about around Node than in the actual code that runs a server. Still, it’s worth taking a blisteringly fast cruise through NodeFileServer.js before moving on. Take another look at the code:
这里关于 Node 本身讨论比作为服务器运行的代码花费更多精力 。不管怎样,在继续前,是值得极速视察一下 NodeFileServer.js。 查看代码:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

First, you have a call to a function called require(). The use of require() has been a long-standing request by programmers. You can actually find this mentioned in some of the discussions on JavaScript modularity, as well as germane to CommonJS, and a pretty cool implementation by O’Reilly author David Flanagan from 2009. In other words, require() may be new to you, but it isn’t an untested, careless piece of Node code. It’s core to using modular JavaScript, and something of which Node takes heavy advantage.
首先,调用了函数 require(),require() 是程序员最常用的函数之一。实际上,你可以在 JavaScript 模块化概念中找到相关的一些讨论,就像 CommonJS ,此外,O’Reilly 作者 Davd Flanagan 在 2009 年完成了一个很酷的实现。换句话说,require() 对于你来说可能是个新鲜事物,但它不是一个没有测试过的一小段 Node 代码。它是模块化 JavaScript 使用的核心,Node 将这一特性发挥的淋漓尽致。

Then, the resulting http variable is used to create a server. That server is handed a function block to run when it’s contacted. This particular function ignores the request completely and just writes out a response, in text/plain, saying simply “Hello Worldn”. Pretty straightforward stuff.
接下来,http 结果变量用以创建一个服务器。这个服务使用一个回调函数,来处理当产生一个连接时的动作。这个特殊的函数彻底忽略了 request, 只是输出一个回应,该回应为以 text/plain 为格式,简单说了 一下 “Hello World”。该逻辑非常简单。

In fact, this lays out the standard pattern for Node usage:
实际上,这里展示了使用 Node 的标准模式:
1.Define the type of interaction and get a variable for working with that interaction (via require()).
2.Create a new server (via createServer()).
3.Hand that server a function for handling requests.
。The request handling function should include a request …
。… and a response.
4.Tell the server to start handling requests on a specific port and IP (via listen).
1.定义交互类型,并获得一个用以处理这个交互的变量(通过require())。
2.创建一个新的服务(通过createServer())。
3.给服务绑定一个回调,用以处理请求。
。处理请求的函数应当包括一个请求…
。…和一个响应
4.通知服务器启动服务,这里需要指定 IP 和端口(通过listen)。

——————————————————————————–
六、Lost in translation
六、解释器之惑
Despite the ease with which you can get a server coded in JavaScript (regardless of whether the actual code-running facility is C or anything else) still begs the question: Should you write a server in JavaScript? To really get a handle on the answer to this question, consider a pretty typical use case.
尽管你可以使用 JavaScript很容易地实现一个服务器(不管,运行代码实际上跑的是 C 代码还是其他什么语言代码),然而回避了一个问题:你需要使用 JavaScript 实现一个服务器吗?为了找到这个问题的答案,我们来考虑一个非常典型的场景。

The JSON round trip
JSON 的处理
You’ve got a typical web application, HTML front-end with CSS styling, and JavaScript for the validation and communication with a server. And because you’re up on the interactive web, you’re using Ajax and not relying purely on a form’s POST to get data to and from the server. If this is you, then you’re probably comfortable with JSON, too, as that’s the almost de facto means of sending data across the wire these days.
你应该有过一种非常典型的 web 应用,前台使用 HTML 和 CSS styling, 同时 JavaScript 用来作数据验证,并和服务器进行数据交互。由于你处于 web 交互的最顶端,你使用 Ajax 而不是纯正地 form post 来提交数据给服务器,或从服务器得到数据。如果你是这样做的话,那么你同样会非常喜欢使用 JSON 。JSON 是如今最流行的传输数据的格式。

So you’ve got an Ajax request that says, for example, “give me more information about some particular guitar on an online auction site.” That request gets thrown across the network to a PHP program running on a server somewhere. The PHP server has to send a lot of information back to the JavaScript requestor, and it’s got to send that information in some format that JavaScript can unpack. So the return information is bundled up into an array, which can then be converted to JSON, sort of like this:
因此,你有个 Ajax 请求,如下所示,“把在线拍卖网站里的某些吉他的信息发给我”。这个请求通过网络到达一个运行 PHP 程序的服务器。PHP 服务器不得不给 JavaScript 返回很多信息,而且这些信息必须以某种形式的数据包发给客户端,而且这个数据包是可以被 JavaScript 解析的。因此返回的信息可以打包成数组,然后转换为 JSON,就像这样:

$itemGuitar = array(
    'id' => 'itemGuitar',
    'description' => 'Pete Townshend once played this guitar while his own axe ' .
        was in the shop having bits of drumkit removed from it.',
    'price' => 5695.99,
    'urls' => array('http://www.thewho.com',
        'http://en.wikipedia.com/wiki/Pete_Townshend')
);

$output = json_encode($itemGuitar);
print($output);

Back on the client, the JavaScript gets this chunk of information, which has changed slightly because of JSON and transmission. The client basically gets something like this:
回到客户端,JavaScript 得到大量的信息,这些信息已经改变了,因为 JSON 和传输。客户端得到如下信息:

{
    "id": "itemGuitar",
    "description": "Pete Townshend once played this guitar...",
    "price": 5695.99,
    "urls": ["http://www.thewho.com", "http://en.wikipedia.com/wiki/Pete_Townshend"]
}

This is pretty standard fare. Then, it’s easy to convert this text “thing” into an object in JavaScript. You just call eval(), like this:
这种转换是标准的,也是相互等价的。接下来,就可以很容易的将这个字符串转换为 JavaScript 对象。你可以调用 eval(),就像这样:

var itemDetails = eval('(' + jsonDataString + ')');

The result is a nice JavaScript object with properties that match up to the JSON array-like structure. Of course, since the jsonDataString usually is returned from a server, you’re more likely to see code like this:
结果是一个不错的 JavaScript 对象,该对象的属性和 JSON 数组的数据结构保持一致。当然,由于jsonDataString 通常是由服务器返回的,你的代码更应该向下面一样:

var itemDetails = eval('(' + request.responseText + ')');

This is the typical JSON round trip. But there are problems here … big, big problems.
这就是最最典型的 JSON 处理,但存在一个非常严重的问题。

Subtlety and nuance destroy solid code
微妙的差别对实体代码的破坏性
(译注:这个小标题着实让人费解,作者这里拐弯抹角的解释了 Node 的一个好处,就是前端和后端都采用同样的语言 JavaScript,在作 JSON 解析时是无障碍的,而当前端使用 JavaScript 作 JSON 编码,后台用 PHP 作 JSON 解码时,多少会因为多种语言的 JSON 解析的实现不同而带来一些兼容性问题)

First, there’s a major problem in that this sort of code relies heavily on a translator. In this case, the translator is the JSON interpreter and related code, and there are in fact two dependencies: a JSON interpreter for Java in the form of what eval() does with the response text, and the JSON interpreter for PHP. As of PHP 5.2.0, that interpreter is included with PHP, but it’s still essentially an external dependency, separate from the core of PHP.
首先,主要问题是,对该种代码的解释器的严重依赖。在上个例子中,解释器就是指 JSON 解析器和相关代码,这儿实际上依赖了两样东西: 对于 Java 一个 JSON 解析器 是以 eval() 来处理响应文本,同时对于 PHP 有个 JSON 解析器。在 PHP 5.2.0 中,已经包含了 JSON 解析器,但却是以外部依赖的形式给出的,并不是内置于 PHP 的内核中。

Now, this isn’t a rant about translation itself. There’s nothing to suggest that there are problems in taking, say, an “l” and turning it into an “i”, or something that’s item 1 in an array and reporting it as being item 2 in an array. There’s a lot of testing that occurs before JSON tools are ever released to ensure that what gets reported is correct, and accurate round tripping from a client to a server and back again are possible. Lots and lots and lots of testing is involved …
但这并不是大肆宣扬解释器的种种。毕竟解释器本身还存在很多问题,比如将“I”解析成了“i”,数组中的元素 1 解释成了 2。当然,在 JSON 工具正式发布之前会有大量的测试,以保证在各种复杂场景中都不会出现错误,包括在客户端的解析结果和在服务器端的解析结果完全一致。无论如何,这都需要大量的测试才行。
现在,不是大肆讲解解释器本身。也不建议,讨论各种问题,比方说,将一个“l”解析成了“i”,或数组中的元素第 1 项被解释成第 2 项。在 JSON 工具正式发布前,还有大量的测试,以确保得正确的结果,在客户端到服务器之间准确来回。大量的测试被涉及…

And that is in fact a problem.
不管怎样,这实际是一个问题。

The dependency of JavaScript and PHP (and C and Lisp and Clojure and Eiffel and … well, see the figure below for all the JSON toolkits floating around for a ton of different languages) on a toolkit is a huge issue. In other words, the problem isn’t the translation but the translator. While programming languages evolve slowly, the uses to which these languages are applied is growing quickly. The result is that JSON is being put to use in areas of complexity that simply didn’t exists or went untouched even a few months ago. And with each new iteration — each new depth of recursion and combination of data types — it’s possible that an area is discovered that the translator doesn’t support.
JavaScript 和 PHP (C 和 Lisp 和 Clojure 和 Eiffel 及……好吧,请参见下图显示了围绕多种不同编程语言的所有的 JSON 的工具包)依赖工具集是一个巨大的问题。换言之,这个问题不在于“翻译”(translation),而是在于“翻译器”(translator)(译注:作者的意思是说 JSON 本身的规则没有问题,反倒是各种语言的 JSON 实现的质量参差不齐,甚至有很多bug)。当编程语言进化缓慢时,这些语言实现的 JSON 使用将迅速增长。其结果是 JSON 将被实现复杂数据结构的解析,该复杂可能根本不存在,或去甚至很长时间不会触及到。而且随着每一个新的迭代 – 每个新深度的递归和数据类型的组合 — 可能发现 JSON 解释器不支持某个区域(新深度或复杂数据组合)。

这里写图片描述
That’s not in itself bad. In fact, it argues for the popularity of JSON that it’s constantly put to new use. But with the “new” comes the “does it support the new?” So JSON has to evolve from time to time, and that means testing, and retesting, and release on tons of platforms. You, the programmer, may have to rearrange your data; or wait on a release to support your needs; or hack at JSON yourself. Again, many of these are just the so-called costs of programming.
大量 JSON 实现本身并不是坏事。事实上,这有利于 JSON 的普及,及 JSON 不断推广到新的用途方面。但对于新领域,不禁要问“JSON 是否支持新领域?”所以,JSON 已经时刻都在进化,这意味着测试和再测试,并在各种平台上发布新版本。你,程序员,可能需要重新组织你的数据;或等待一个新版本来支持你的需求;或构建自己的 JSON。而这些刚好是编程的成本。

But imagine you could ditch the translation — and therefore the translator — altogether. Imagine you could write, not JSON round tripping, but JavaScript end to end.
但想象一下你可以抛开翻译 – 及解释器 – 一起。想象一下你所写的,不需要 JSON 处理,而是 JavaScript 端到端的使用。

That’s the promise of Node. All the text you’ve just read — about PHP including JSON in 5.2.0 but not before, about arrays becoming objects, about data being configured in new ways and requiring new things from JSON — it all goes away when you have JavaScript sending data and receiving and responding to that data.
这正是 Node 许诺的, JavaScript 的端到端使用。刚刚你读到的所有文字 – 关于内嵌 JSON 的 PHP 5.2.0、关于将数组转换为对象、关于采用新的方法组织数据及从 JSON 请求新东西 – 当你使用 JavaScript 来发送数据,接受和响应该数据时, Node 使这一切的问题都消失。

eval() in JavaScript is (Potentially) the Devil
JavaScript 中 eval() 的潜在隐患

As if that’s not enough reason to look seriously at Node, there’s the pesky issue of running eval() on a string. It’s long been accepted that eval() is dangerous stuff. It runs code that you can only see as textual data; it’s the equivalent of that “Run Your SQL by typing it in here” unvalidated text box, open to SQL injection and malicious intent. It’s quite possible that every time eval() is passed in a string, a puppy somewhere in the Midwest shivers and a mom on the Eastern Seaboard stubs her toe and curses. It’s that precarious. There’s plenty to read about online, and it’s not worth going into in detail here. Just Google “eval JavaScript evil” or “eval JavaScript injection” to get a good taste of the issues.
似乎在 Node 中没有足够的理由看出该问题严重,但在一段字符串上运行 eval() 是个恼人的问题。eval() 被长期认为是非常危险的东西。eval() 能运行你能看到的文本数据的代码;等同于“在这里直接敲入 SQL 代码来执行”,这是不安全无验证的输入,这实际上是恶意 SQL 注入攻击。这相当于每次 eval() 执行一段字符串时,(美国)中西部的一只小狗都会瑟瑟发抖,东部海滩上的某位母亲的脚趾会被刺伤并受到诅咒。eval() 非常危险。网上有很多关于此的资料,这里不再赘述。可以用 google 查询“eval JavaScript evil”或者“eval JavaScript injection”获取更多信息。

Still, Node without any context doesn’t allow you to avoid eval(), so there are potentially still shivering puppies out there. However, Node used as it’s intended absolutely gets you around the typical eval() problems. Node is often called evented JavaScript or evented I/O, and that little word — “evented” — is hugely important. But to get a hold of what evented really means, and why it gets you out of the dangers of eval(), you’ve got to understand not just how JSON is typically round tripped in applications, but how the very structure of applications on the web are typically architected.
当然,没有任何背景, Node 是不允许你避开 eval() ,因此 eval() 的隐患在 Node 依然存在。然而, Node 的使用,常表现出 eval() 的典型的问题。Node 被常调用基于事件的 JavaScript, 或基于事件的 I/O,这里所说的 –“基于事件” – 是 Node 中非常重要的概念。但要彻底理解什么是基于事件,以及为什么基于事件能让你规避 eval() 的危险,则需要你理解 JSON 在应用之中是如何不处于问题中,此外还要搞清楚在 web 上应用的结构如何被构建的。

—————————————————–—————————**
七、Today’s web is a big-event web**
七、基于事件的 Web 应用
Typical web forms are “big-event” submitters. In other words, lots of data entry and selection happens — a user fills out text boxes, selects choices from combo boxes, selects items from a list, and so on — and then all of that information is submitted to a server. There’s a single “big event” from the programming perspective: the submission of all that form data, usually through a POST. That’s pretty much how the web operated, pre-Ajax.
传统的 Web 表单是“大事件”提交者。换句话说,大量的数据输入和选择发生 – 用户输入文本框,点选复选框,从列表中选中某些项等等 – 然后所有这些数据被提交给服务器。从编程的角度看是一个单独的”大事件”:使用 POST 方式将表单数据提交。这也是基于 Ajax 的 Web 应用的工作原理。

Sending lots of data at one time
一次性发送大量数据

With Ajax, there is a little more of what’s called evented programming. There are more events that trigger interaction with the server. The classic case is the entry of a zip code, and then a resulting call to the server to get a city and state. With Ajax and the XmlHttpRequest, tons of data didn’t have to be gobbed up and thrown to the server all at once. However, that doesn’t change the reality that the web is still mostly a big-event place. Ajax is used far more often to achieve interesting visuals, do quick validations, and submit forms without leaving a page than it is to create truly evented web pages. So even though a form isn’t submitting a big gob of information with a POST, an Ajax request is doing the same thing.
对于 Ajax 来说,这是可以和基于事件编程扯上一点关系的。大量的事件触发了和服务器端的交互。典型的场景是输入一个邮政编码,然后发送请求到服务器获得城市和省的名称。这里通过 Ajax 和 XmlHttpRequest, 并不需要将很多数据一次性扔给服务器。但这并不能改变大部分 web 应用大部分是一个大事件的现状。Ajax 已经更广泛的用于很多有意思的视觉效果,快速的验证,无刷新提交数据,而不是真正创建一个事件 web 页面。因此,尽管并未通过提交表单来发起一个真正的 POST 请求,通过 Ajax 可以模拟 POST 表单提交。

Honestly, that’s only partly the fault of less-than-creative Ajax programmers. Every time you send off a request — no matter how small — there’s a lot of network traffic going on. A server has to respond to that request, usually with a new process in its own thread. So if you really move to an evented model, where you might have 10 or 15 individual micro-requests going from a single page to a server, you’re going to have 10 or 15 threads (maybe less, depending on how threads are pooled and how quickly they’re reclaimed on the server) firing up. Now multiply that by 1,000 or 10,000 or 1,000,000 copies of a given page floating around … and you could have chaos. Network slowdown. System crashes.
老实说,这只是没有创意的 Ajax 程序员的过失。每次您发送了一个请求 – 无论是多么小 – 都会有大量的网络交互。服务器必须针对这个请求作出响应,通常是在自己的线程中开辟一个新的进程。因此,如果你真正置身于一个事件模型中,你可能需要通过发起 10 到 15 个单独的小请求,从一个页面和一个服务器,你将有 10 到 15 个线程产生(可能更少,这取决于服务器处理新请求时分配线程池的策略),当这个数量乘以 1000 或者 10000 或者 100000 时(译注:每个页面需要 10 个请求,那么越多用户访问这个页面,所发起的请求个数就会越来越多),就会出现内存溢出、逻辑交错带来的冲突、网络瘫痪、系统崩溃这些问题。

The result is that, in most cases, the Web needs to be, at a minimum, a medium-event place. The result of this concession is that server-side programs aren’t sending back tiny responses to very small and focused requests. They’re sending back multiple bits of data, and that requires JSON, and then you’re back to the eval() problem. The problem is eval(), sure, but the problem is also — from a certain perspective, at least — the nature of the web and threading and HTTP traffic between a web page and a server-side program responding to that request.
结果是,在大多数场景中,Web 应用需要保持对事件的最小依赖。有一个折衷方案,就是服务器端程序不发送小的回应给非常小且针对性的请求。他们发送回大量 bit 的数据,通常是 JSON 数据,这时就又遇到了eval()的问题。问题当然出在 eval() 身上 – 但至少从某个角度来说 –也就是在一个 Web page 和响应请求的服务器端之间 web 和线程及 HTTP 交互的本质。

(Some of you more advanced JavaScript folks are screaming at this point, because you know better than to use eval(). Instead, you’re using something like JSON.parse() instead of eval(). And there are also some compelling arguments for careful usage of eval(). These are things worth screaming about. Still, just see how many questions there are surrounding eval() on sites like Stack Overflow and you’ll realize that most folks don’t use eval() correctly or safely. It’s a problem, because there are lots of intermediate programmers who just aren’t aware of the issues around eval().)
或许有些 JavaScript 高手对上文提到的问题不以为然,因为你知道有很多方法来规避直接 eval() 带来的问题。你会使用诸如 JSON.parse() 来代替 eval()。同样有很多令人信服的论据鼓励我们小心的使用 eval()。这些东东都是值得进一步讨论的。但不管怎样,看一看 eval() 带来了太多类似栈溢出(Stack Overflow)这类的问题吧,你会发现大部分程序员并未正确或者安全的使用 eval()。这着实是一个问题。因为太多菜鸟程序员似乎根本没有意识到 eval() 的问题有多严重。

Sending a little data at all times
在任何时候发送少量的数据

Node brings a different approach to the party: it seeks to move you and your web applications to an evented model, or if you like, a “small event” model. In other words, instead of sending a few requests with lots of data, you should be sending tons of requests, on lots of events, with tiny bits of data, or requests that need a response with only a tiny bit of data. In some cases, you have to almost recall your GUI programming. (All the Java Swing folks can finally use their pent-up GUI knowledge.) So a user enters their first and last name, and while they’re moving to the next box, a request is already requesting validation of just that name against existing names. The same is true for zip codes, and addresses, and phone numbers. There’s a constant stream of requesting and responding happening, tied to almost every conceivable event on a page.
Node 带来了不同的方法思路:Node 试图将你和你的 Web 应用程序转为基于事件触发的模式,或者说“小事件”的模式。换句话说,替代了用少量请求发送大量数据,你应该发送大量的请求,基于大量事件,带有少量数据,或者需要少量数据的回应的请求。在某些情况下,你几乎只记得你的 GUI 编程。 (所有的 Java Swing 程序员终于可能只用自己的图形用户界面(GUI)的知识。)。因此,用户输入他们的第一个和最后一个名字,同时当他们移动到下一个框时,请求已经在请求对现有名称的验证名字。对于邮政编码,和地址,和电话号码同样如此。有请求和回应发生的固定流,被绑在一个页面上每一个可以想象的事件上。

So what’s the difference? Why is this possible with Node, and aren’t the same issues around threading existent here? Well, no, they’re not. Node’s own site explains their philosophy the best:
那么,有什么不同吗?为什么 Node 可以做到,而不是在线程这里存在相同的问题吗?哦,不,它们没有。Node 自己的网站,完美地解释了他们的哲学:

Node’s goal is to provide an easy way to build scalable network programs. In the “hello world” web server example … many client connections can be handled concurrently. Node tells the operating system (through epoll, kqueue, /dev/poll, or select) that it should be notified when a new connection is made, and then it goes to sleep. If someone new connects, then it executes the callback. Each connection is only a small heap allocation.
Node 的目标是提供一种简单的方式来构建可伸缩的网络程序。在“Hello World”的 Web 服务器的例子……可以同时处理很多客户端的连接。Node 告诉操作系统(通过 epoll ,kqueue。 /dev/poll, or select),当了一个新连接产生,Node 应该得到通知,然后 Node 进入睡眠状态。如果又有新的连接,然后 Node 执行回调。每个连接是只有非常小的 heap 开销。

Node has no blocks, no threads competing for the same resource (Node is happy to just let things happen however they happen), nothing that has to start up upon request. Node just sits around waiting (quite literally; unused Node responders are sleeping). When a request comes in, it’s handled. This results in very fast code, without uber-programmers writing the server-side behavior.
Node 是非阻塞的,没有线程争用相同的资源(Node 非常乐于在一些事发生时触发另一些事生),没有什么必须根据请求来启动。Node 只是坐在那里等待(毫不夸张地说,未使用的 Node 响应者都在睡觉)。当一个请求到达时,它被处理。这将导致非常高效的代码,可以不用超级程序员来编写服务器端的代码。

Yes, chaos can ensue
没错,混乱不可避免

It’s worth pointing out that this model does allow all the problems that any non-blocking system allows to come into play: one process (not thread) writing to a data store while another one grabs just-invalidated data; intrusions into what amounts to a transaction; and so on. But realize that the majority of event-based programming on a web form is read-only! How often are you actually modifying data in a micro-request? Very rarely. Instead, there’s a constant validation, data lookup, and querying going on. In these cases, it’s better to just fire away with the requests. The database itself may add some locking, but in general, good databases will do this much more efficiently than server-side code, anyway; and they’ll certainly handle things better than an operating system will spin up and down threads for a generic, “a web response came in” process.
必须指出的是,非阻塞系统引起的问题也会出现在这种编程模式中:一个进程(非线程)进行一个数据存储操作,然而另外一个进程抓取到无效的数据;干扰到一组操作;等等(译注:作者的意思是说多个操作同时发生或者没有按照预定顺序发生时,会产生混乱,也就是说,操作本身并不是原子性的和顺序的)。但要注意,在 web form 上基于事件编程模式的大多数都是“只读的”!通过“微请求”来修改数据的情况,非常罕见。相反,通过微请求来验证数据合法性、查询数据的情形,则非常常见。这些情况下,最好直接根据请求作响应。数据库本身会作加锁操作,但一般来讲,一个优秀的数据库完全可以高效的做到数据操作的加锁解锁,而不用服务器端的程序代码去做;它们比操作系统能更好处理这些事,即将为一个普通 “web 响应到来”进程, 来启动和释放线程。

Additionally, Node does have plans to allow for process forking, and the HTML5 Web Workers API is the engine that will probably make this feature go. Still, if you move to an evented model for your web application, you’ll probably run into an issue where you might want threading in less than one out of 100 situations. Still, the changes are best in how you think about your web applications, and how often you send and receive data from a server, rather than in how Node works.
此外,Node 也计划实现“进程分支”(process forking),HTML5 Web Workers API 引擎,将可能支持 进程分支 的特性。同样,如果你采用基于事件的模型来架构 web 应用,你的程序可能遇到一个问题,即同时不止一个至少有 100 多个场景需要线程。然而, 变化是,怎样看待你的 web 应用,平常怎样发送和接受来自父服务器的数据,而不在乎 Node 如何工作。

——————————————————————————–
八、In the right place at the right time
八、Node 的用武之地*

There’s another web pattern at work here, and it’s probably far more important than whether you use Node or not, and how evented your web applications are. It’s simply this: use different solutions for different problems. Even better, use the right solution for a particular problem, regardless of whether that’s the solution you’ve been using for all your other problems.
这里讨论另一种 web 运行模式,它可能远比你是否使用 Node 与否更重要,以及如何使你的 Web 应用程序基于事件触发。简单来说:使用不同的解决方案,来针对不同的问题。最好的是,使用正确的解决方案,解决特定的问题,无论该方法能否被你用来解决所有其他问题。

There’s a certain inertia in not just web design, but all of programming. That inertia can be stated axiomatically like this: the more you learn, use, and become good at a certain approach or technique or language, the more likely you are to use that approach/technique/language widely. It’s one of those principles that sounds good until you dig deeply. Yes, it’s good to learn a language or toolkit well, and to employ it widely. But this inertia often causes you to use a tool because you know it, rather than because it’s the right tool.
不止在 web 设计领域,而是所有编程中,都有某种惯性。这样惯性就像公理一样被描述:你越学习,使用,且善于某种方法或技术或语言,你越想使用这种方法/技术/语言到更大地范围。这个原则听起来不错,直到你深入挖掘。没错,擅长很好的学好一种语言或工具, 同时广泛使用它。但是, 惯性常常导致你只使用一种工具,因为这是你掌握的,而不是因为它是正确的工具。

Look at Ajax, something already discussed. Initially, Ajax provided a solid approach to sending quick requests, without form submissions, to a server. Now it’s become a drop-in replacement for all form submissions. That’s taking a technology, learning it, applying it, and then eventually over-applying it. There’s still a solid place for form submissions — when a form needs to be submitted! As simple as it sounds, there are tends of thousands of web applications submitting forms with Ajax, just because the lead web developer is up on Ajax.
来看一下 Ajax,有些事已经有太多的讨论。最初,Ajax 提供一个可靠的解决方案,来发送不带 form 的提交的快速请求给服务器。而如今,Ajax 被滥用于所有 form 的提交访问替代。这就是采取一种技术、学习它、应用它,然后“滥用它”。对于表单提交仍然是一个可靠的方法 – 当一个 form 需要提交时!简单来说,实际上还有成千上万的 web 应用提交 forms 滥用了 Ajax ,仅仅因为领导 web 开发者是基于 Ajax 的。

In the same vein, it’s possible to get excited about Node — probably because you buy into all the splendid and wise observations you’ve been reading — and then use it everywhere. Suddenly, you’re replacing all your PHP and Perl back-ends with Node. The result? A mess. In fact, you’ll be forced to have several web forms do just what Node isn’t meant for: submit big chunks of data to JavaScript on the server via Node, and force that JavaScript to either send back a chunk of JSON that’s got to be parsed or eval()ed, or send back a full-blown HTML page or an HTTP redirect.
本着同样的精神,可能更关心 Node – 可能是因为你发现它的种种好处 – 然后想到处使用它。突然间,你有使用 Node 替换所有的 PHP 和 Perl 后台。 结果呢? 一团糟。事实上,你将被强迫,来使 node 处理一些个网页 forms,而 node 不善于: 通过 node 提交大数据块给在服务器上的 JavaScript,同时强迫 JavaScript 来返回 被 parsed 或 eval()ed 的 JSON 块,或发回一个成熟的 HTML 页面或 HTTP 重定向。

But that’s simply not what Node is best at. It’s great at micro-requests; at evented I/O. Use Node for quick communication between a web page and a server. Use form submissions to send big chunks of data to the server. Use PHP and Perl to do heavy database lifting and generate dynamic HTML pages. Use Node to provide a means for server-side JavaScript to run and handle small requests. Throw in Rails and Spring and servlets and whatever else you need. But make your decisions based upon the problem you’re solving, rather than what you happen to know best at the time.
但是,这根本就不是什么Node 最擅长的。Node 擅长于细小的请求; 基于事件的 I/O。使用 Node 来解决网页和服务器之间的快速沟通。使用表单(form)提交来发送大块数据到服务器。使用 PHP 和 Perl 做大量数据库的操作,并生成动态的 HTML 页面。使用 Node,来提供一种收到,为服务器端的 JavaScript 运行和处理小的请求。不管是采用 Rails 和 Spring 和 servlet, 只要按需索取即可。但要根据你解决的问题来做出你的决定,而不是当时你擅长的技术。

Node’s promise of simplicity
Node 的简单的初衷

There’s one last note worth making. When you take this broad approach to programming, you’ll often find that you’re not having to go as deeply into each toolkit, API, and framework you use. By using your tools for what they’re best at, you don’t need to be able to staple with hammers or measure with drills. Using tools for their intended purpose typically means you use the core capabilities more. So while you’re creating generalists — programmers that know lots of things — you are also reducing the need for specialists — programmers that know one or two things really, really well. Of course, every pointy-haired boss also realizes that those specialists are really, really expensive and hard to find.
还有最后一点需要注意。当你使用以上方法来编程时,你常常会发现,你不必对每个工具、API 和所使用的框架,都了解达到精通。通过使用你的工具,来做他们擅长的,而不是将锤子当成钻头来使用。了解每个工具所适用的场景,意味你能更好的使用其核心的能力。因此当你想变成超人式的通才 – 程序员往往什么都想知道 – 你离“专家”也就越来越远 – 所谓专家,就是指在一两个方面达到非常精通。当然,每个老板都知道这些专家都非常可贵,很难找到。

Learning Node might take a little effort, but it’s going to pay off. Why? Because you’re afforded solutions to your web application problems that require only JavaScript to solve. That means your existing JavaScript expertise comes into play. And when you do need to use PHP or Perl — because it’s the right solution for a particular problem — you don’t need a PHP or Perl guru. You need to know the basics, and those needs can be expanded when the problem requires expansion. Stretching comes at the behest of new problems, rather than stretching poor solutions thinly.
学习 Node 可能会有些吃力,但是非常值得的。为什么?因为你可以提供基于 JavaScript 的 web 应用的解决方案。这意味着你已有的 JavaScript 编程技能不会丢掉。同时,当你需要使用 PHP 或者Perl 时 – 因为它能解决一个特殊的问题 – 你不必成为一个 PHP 或 Perl 大师。你只需要知道其基本知识,且学习扩展当问题解决需要扩展时扩展。扩展是来自新问题的需要,而不是扩展解决方案。

Your biggest challenge is the continual move to a web that is made up of smaller pieces, talking more often, and the combination of what can seem like a dizzying array of technologies. However, taking the core features of 100 technologies is always going to serve you better than taking 100% of one technology and trying to solve 100 problems. Node and evented I/O isn’t a solution to every problem, but it sure is a solution to some important problems.
你最大的挑战是,不断移向一种 web, 该 web 是由更小的块,更多会话,及令人眼花缭乱的技术的组合所构成。然而,使用 100 种技术的核心特点将总是能比使用一种技术的 100%,能更好的服务于你,并能更好地解决 100 个问题。Node 和 基于事件的 I/O 是不能解决所有问题的,但可以肯定的是提供了一些重要的问题的解决方案。

Related:
参考文献

Node: Up and Running (Book)
The secrets of Node’s success(http://radar.oreilly.com/2011/06/node-javascript-success.html
Why a JavaScript hater thinks everyone needs to learn JavaScript in the next year(http://radar.oreilly.com/2010/11/new-directions-in-web-architec.html
JavaScript spread to the edges and became permanent in the process
What is Node.js and what does it do? (Video)
What is HTML5?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值