什么是Node.js?(1)(3)
快速入门手册
围绕Node的话题总是会比纯粹运行在服务器端的代码更值得花点时间来讨论。不管怎样,我们还是从一段代码开始我们的话题,概览一下NodeFileServer.js文件,观察代码:
- var http = require('http');
- http.createServer(function (req, res) {
- res.writeHead(200, {'Content-Type': 'text/plain'});
- res.end('Hello Worldn');
- }).listen(1337, "127.0.0.1");
- console.log('Server running at http://127.0.0.1:1337/');
首先调用了函数require(),require()是程序员最常用的函数之一。实际上,在CommonJS规范中也有提到这个函数,在讨论到关于JavaScript模块概念的时候有提及,此外,Davd Flanagan在2009年的一个很酷的实现中也有提到。换句话说,require()对于你来说可能是个新鲜事物,但它不是Node随意添加的一个函数,他是使用JavaScript进行模块化编程的核心概念,Node将这一特性发挥的淋漓尽致。
接下来,http变量用以创建一个服务器。这个服务使用一个回调函数来处理当产生一个连接时的动作。这里的回调函数并未对请求作过多修饰,仅仅以text/plain格式输出一个字符串“Hello World”作为请求响应。这个逻辑非常简单。
实际上,这里展示了使用Node的标准模式:
定义交互类型,并获得一个用以处理这个交互的变量(通过require())。
创建一个新的服务(通过createServer())。
给服务绑定一个回调,用以处理请求。包括处理请求的函数应当包括一个请求…,以及一个响应
通知服务器启动服务,这里需要指定IP和端口(通过listen)。
解释器之惑
尽管通过这种方法可以使用JavaScript轻易的实现一个服务(不管运行代码的虚机实际上跑的是C程序还是其他什么程序),这种做法回避了一个问题:你需要使用JavaScript写出一个服务器吗?为了找到这个问题的答案,我们来考虑一个非常典型的场景。
JSON的处理
这是一种非常典型的web应用,前台使用HTML和CSS,JavaScript用来作数据验证,并和后台进行数据交互。由于你处于web交互的最顶端,你使用Ajax提交数据到后台并从后台获取数据,而不是单单依靠表单提交来实现。如果你是这样做的话,那么你同样会非常喜欢使用JSON的。JSON是如今最流行的传输数据的格式。
因此,这个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);
回到客户端,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"]
- }
这种转换是标准的,转换前后也是相互等价的。接下来,就可以将这个字符串转换为JavaScript对象,可以调用eval(),就像这样:
- var itemDetails = eval('(' + jsonDataString + ')');
计算结果是一个普通的JavaScript对象,这个对象的属性和JSON数组的数据结构保持一致。当然,由于jsonDataString通常是由服务器返回的,通常需要这样来解析返回结果:
- var itemDetails = eval('(' + request.responseText + ')');
这就是最最典型的JSON处理,但存在一个非常严重的问题。
对实体代码微妙的破坏性
(译注:这个小标题着实让人费解,作者这里拐弯抹角的解释了Node的一个好处,就是前端和后端都采用同样的语言JavaScript,在作JSON解析时是无障碍的,而当前端使用JavaScript作JSON编码,后台用PHP作JSON解码时,多少会因为多种语言的JSON解析的实现不同而带来一些兼容性问题)
首先,这类代码的一个主要问题是,它对解释器的依赖比较严重。在上个例子中,解释器就是指内置的JSON解析器或者实现解析JSON的代码,这实际上依赖了两样东西:和eval()解析响应文本的操作一样的基于Java的JSON解析器,以及基于PHP的JSON解析器。在PHP5.2.0中已经包含了JSON解析器,但却是以外部依赖的形式给出的,并不是内置于PHP的内核中。
但这并不是大肆宣扬解释器的种种。毕竟解释器本身还存在很多问题,比如将“I”解析成了“i”,数组中的元素1解释成了2。当然,在JSON工具正式发布之前会有大量的测试,以保证在各种复杂场景中都不会出现错误,包括在客户端的解析结果和在服务器端的解析结果完全一致。无论如何,这都需要大量的测试才行。
不管怎样,JSON依然存在很多实际的问题。
基于某种语言(基于JavaScript或者PHP)的JSON解析器选择是一个很大的问题。换句话说,问题不是在于“翻译”(translation)而在于“翻译器”(translator)(译注:作者的意思是说JSON本身的规则没有问题,反倒是各种语言的JSON实现的质量参差不齐,甚至有很多bug)。当一个语言的版本比较稳定时,基于这门语言的JSON解析器的运用和推广会比较快。结果是,JSON解析器变的越来越强大,以至于可以解析任意复杂的数据结构,即便这么复杂的数据结构根本不会实际用到。反之,每次迭代中(每次计算迭代的路径和数据类型的组合),也很有可能出现JSON解释器无法解析的数据结构(或者很深的JSON路径)的情况。
下图就是可选的JSON解释器

这并不是说JSON本身很糟糕,实际上,我们认为JSON的流行正是得益于其在新领域中的应用(译注:作者的言外之意是,在新领域中的初次JSON实现往往伴随很多问题)。对于新的领域,我们不禁要问:“这个新东东支持JSON吗?” 因此,JSON需要不断进化,需要不断的测试,不断的兼容新的平台。而作为程序员的,可能需要重新组织你的数据结构,或者等待新的版本出现以满足你的需求,或者干脆直接hack JSON。而这些正是我们所说的编程资源的浪费。
假设你可以自己动手丰衣足食实现一个解释器,即便这样,你也没有通过“抄近道”拣到便宜,而是用JavaScript重复造轮子而已。
而Node则规避了此类问题,刚刚你读到的文字——关于内嵌JSON的PHP5.2.0、关于将对象转换为数组、关于采用新的结构组织数据的方式、关于JSON中新特性的实现——这一切扰人的问题在Node中都将不复存在,因为前端通过JavaScript作JSON编码,后台使用JavaScript作JSON解码,永远不会出问题。
- 上一篇:JavaScript原型继承
- 下一篇:6个提高交互体验的JavaScript库






