Node入门作者:ManuelKiessling翻译:goddyzhao&GrayZhang&MondayChen关于本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识。本书绝不是一本“HelloWorld”的教程。状态你正在阅读的已经是本书的最终版。因此,只有当进行错误更正以及针对新版本Node.js的改动进行对应的修正时,才会进行更新。本书中的代码案例都在Node.js0.4.9版本中测试过,可以正确工作。读者对象本书最适合与我有相似技术背景的读者:至少对一门诸如Ruby、Python、PHP或者Java这样面向对象的语言有一定的经验;对JavaScript处于初学阶段,并且完全是一个Node.js的新手。这里指的适合对其他编程语言有一定经验的开发者,意思是说,本书不会对诸如数据类型、变量、控制结构等等之类非常基础的概念作介绍。要读懂本书,这些基础的概念我都默认你已经会了。然而,本书还是会对JavaScript中的函数和对象作详细介绍,因为它们与其他同类编程语言中的函数和对象有很大的不同。本书结构读完本书之后,你将完成一个完整的web应用,该应用允许用户浏览页面以及上传文件。当然了,应用本身并没有什么了不起的,相比为了实现该功能书写的代码本身,我们更关注的是如何创建一个框架来对我们应用的不同模块进行干净地剥离。是不是很玄乎?稍后你就明白了。本书先从介绍在Node.js环境中进行JavaScript开发和在浏览器环境中进行JavaScript开发的差异开始。紧接着,会带领大家完成一个最传统的“HelloWorld”应用,这也是最基础的Node.js应用。最后,会和大家讨论如何设计一个“真正”完整的应用,剖析要完成该应用需要实现的不同模块,并一步一步介绍如何来实现这些模块。可以确保的是,在这过程中,大家会学到JavaScript中一些高级的概念、如何使用它们以及为什么使用这些概念就可以实现而其他编程语言中同类的概念就无法实现。该应用所有的源代码都可以通过本书Github代码仓库.目录•关于o状态o读者对象o本书结构•JavaScript与Node.jsoJavaScript与你o简短申明o服务器端JavaScripto“HelloWorld”•一个完整的基于Node.js的web应用o用例o应用不同模块分析•构建应用的模块o一个基础的HTTP服务器o分析HTTP服务器o进行函数传递o函数传递是如何让HTTP服务器工作的o基于事件驱动的回调o服务器是如何处理请求的o服务端的模块放在哪里o如何来进行请求的“路由”o行为驱动执行o路由给真正的请求处理程序o让请求处理程序作出响应不好的实现方式阻塞与非阻塞以非阻塞操作进行请求响应o更有用的场景处理POST请求处理文件上传o总结与展望JavaScript与Node.jsJavaScript与你抛开技术,我们先来聊聊你以及你和JavaScript的关系。本章的主要目的是想让你看看,对你而言是否有必要继续阅读后续章节的内容。如果你和我一样,那么你很早就开始利用HTML进行“开发”,正因如此,你接触到了这个叫JavaScript有趣的东西,而对于JavaScript,你只会基本的操作——为web页面添加交互。而你真正想要的是“干货”,你想要知道如何构建复杂的web站点——于是,你学习了一种诸如PHP、Ruby、Java这样的编程语言,并开始书写“后端”代码。与此同时,你还始终关注着JavaScript,随着通过一些对jQuery,Prototype之类技术的介绍,你慢慢了解到了很多JavaScript中的进阶技能,同时也感受到了JavaScript绝非仅仅是window.open()那么简单。.不过,这些毕竟都是前端技术,尽管当想要增强页面的时候,使用jQuery总让你觉得很爽,但到最后,你顶多是个JavaScript用户,而非JavaScript开发者。然后,出现了Node.js,服务端的JavaScript,这有多酷啊?于是,你觉得是时候该重新拾起既熟悉又陌生的JavaScript了。但是别急,写Node.js应用是一件事情;理解为什么它们要以它们书写的这种方式来书写则意味着——你要懂JavaScript。这次是玩真的了。问题来了:由于JavaScript真正意义上以两种,甚至可以说是三种形态存在(从中世纪90年代的作为对DHTML进行增强的小玩具,到像jQuery那样严格意义上的前端技术,一直到现在的服务端技术),因此,很难找到一个“正确”的方式来学习JavaScript,使得让你书写Node.js应用的时候感觉自己是在真正开发它而不仅仅是使用它。因为这就是关键:你本身已经是个有经验的开发者,你不想通过到处寻找各种解决方案(其中可能还有不正确的)来学习新的技术,你要确保自己是通过正确的方式来学习这项技术。当然了,外面不乏很优秀的学习JavaScript的文章。但是,有的时候光靠那些文章是远远不够的。你需要的是指导。本书的目标就是给你提供指导。简短申明业界有非常优秀的JavaScript程序员。而我并非其中一员。我就是上一节中描述的那个我。我熟悉如何开发后端web应用,但是对“真正”的JavaScript以及Node.js,我都只是新手。我也只是最近学习了一些JavaScript的高级概念,并没有实践经验。因此,本书并不是一本“从入门到精通”的书,更像是一本“从初级入门到高级入门”的书。如果成功的话,那么本书就是我当初开始学习Node.js最希望拥有的教程。服务端JavaScriptJavaScript最早是运行在浏览器中,然而浏览器只是提供了一个上下文,它定义了使用JavaScript可以做什么,但并没有“说”太多关于JavaScript语言本身可以做什么。事实上,JavaScript是一门“完整”的语言:它可以使用在不同的上下文中,其能力与其他同类语言相比有过之而无不及。Node.js事实上就是另外一种上下文,它允许在后端(脱离浏览器环境)运行JavaScript代码。要实现在后台运行JavaScript代码,代码需要先被解释然后正确的执行。Node.js的原理正是如此,它使用了Google的V8虚拟机(Google的Chrome浏览器使用的JavaScript执行环境),来解释和执行JavaScript代码。除此之外,伴随着Node.js的还有许多有用的模块,它们可以简化很多重复的劳作,比如向终端输出字符串。因此,Node.js事实上既是一个运行时环境,同时又是一个库。要使用Node.js,首先需要进行安装。关于如何安装Node.js,这里就不赘述了,可以直接参考官方的安装指南。安装完成后,继续回来阅读本书下面的内容。“HelloWorld”好了,“废话”不多说了,马上开始我们第一个Node.js应用:“HelloWorld”。打开你最喜欢的编辑器,创建一个helloworld.js文件。我们要做就是向STDOUT输出“HelloWorld”,如下是实现该功能的代码:console.log(HelloWorld);保存该文件,并通过Node.js来执行:nodehelloworld.js正常的话,就会在终端输出HelloWorld。好吧,我承认这个应用是有点无趣,那么下面我们就来点“干货”。一个完整的基于Node.js的web应用用例我们来把目标设定得简单点,不过也要够实际才行:•用户可以通过浏览器使用我们的应用。•当用户请求时,可以看到一个欢迎页面,页面上有一个文件上传的表单。•用户可以选择一个图片并提交表单,随后文件将被上传到,该页面完成上传后会把图片显示在页面上。差不多了,你现在也可以去Google一下,找点东西乱搞一下来完成功能。但是我们现在先不做这个。更进一步地说,在完成这一目标的过程中,我们不仅仅需要基础的代码而不管代码是否优雅。我们还要对此进行抽象,来寻找一种适合构建更为复杂的Node.js应用的方式。应用不同模块分析我们来分解一下这个应用,为了实现上文的用例,我们需要实现哪些部分呢?•我们需要提供Web页面,因此需要一个HTTP服务器•对于不同的请求,根据请求的URL,我们的服务器需要给予不同的响应,因此我们需要一个路由,用于把请求对应到请求处理程序(requesthandler)•当请求被服务器接收并通过路由传递之后,需要可以对其进行处理,因此我们需要最终的请求处理程序•路由还应该能处理POST数据,并且把数据封装成更友好的格式传递给请求处理入程序,因此需要请求数据处理功能•我们不仅仅要处理URL对应的请求,还要把内容显示出来,这意味着我们需要一些视图逻辑供请求处理程序使用,以便将内容发送给用户的浏览器•最后,用户需要上传图片,所以我们需要上传处理功能来处理这方面的细节我们先来想想,使用PHP的话我们会怎么构建这个结构。一般来说我们会用一个ApacheHTTP服务器并配上mod_php5模块。从这个角度看,整个“接收HTTP请求并提供Web页面”的需求根本不需要PHP来处理。不过对Node.js来说,概念完全不一样了。使用Node.js时,我们不仅仅在实现一个应用,同时还实现了整个HTTP服务器。事实上,我们的Web应用以及对应的Web服务器基本上是一样的。听起来好像有一大堆活要做,但随后我们会逐渐意识到,对Node.js来说这并不是什么麻烦的事。现在我们就来开始实现之路,先从第一个部分--HTTP服务器着手。构建应用的模块一个基础的HTTP服务器当我准备开始写我的第一个“真正的”Node.js应用的时候,我不但不知道怎么写Node.js代码,也不知道怎么组织这些代码。我应该把所有东西都放进一个文件里吗?网上有很多教程都会教你把所有的逻辑都放进一个用Node.js写的基础HTTP服务器里。但是如果我想加入更多的内容,同时还想保持代码的可读性呢?实际上,只要把不同功能的代码放入不同的模块中,保持代码分离还是相当简单的。这种方法允许你拥有一个干净的主文件(mainfile),你可以用Node.js执行它;同时你可以拥有干净的模块,它们可以被主文件和其他的模块调用。那么,现在我们来创建一个用于启动我们的应用的主文件,和一个保存着我们的HTTP服务器代码的模块。在我的印象里,把主文件叫做index.js或多或少是个标准格式。把服务器模块放进叫server.js的文件里则很好理解。让我们先从服务器模块开始。在你的项目的根目录下创建一个叫server.js的文件,并写入以下代码:varhttp=require(http);http.createServer(function(request,response){response.writeHead(200,{Content-Type:text/plain});response.write(HelloWorld);response.end();}).listen(8888);搞定!你刚刚完成了一个可以工作的HTTP服务器。为了证明这一点,我们来运行并且测试这段代码。首先,用Node.js执行你的脚本:nodeserver.js接下来,打开浏览器访问,你会看到一个写着“HelloWorld”的网页。这很有趣,不是吗?让我们先来谈谈HTTP服务器的问题,把如何组织项目的事情先放一边吧,你觉得如何?我保证之后我们会解决那个问题的。分析HTTP服务器那么接下来,让我们分析一下这个HTTP服务器的构成。第一行请求(require)Node.js自带的http模块,并且把它赋值给http变量。接下来我们调用http模块提供的函数:createServer。这个函数会返回一个对象,这个对象有一个叫做listen的方法,这个方法有一个数值参数,指定这个HTTP服务器监听的端口号。咱们暂时先不管http.createServer的括号里的那个函数定