Node应用程序构建——使用MongoDB和Backbone

978-7-115-34629-2
作者: 【美】Mike Wilson
译者: 林冀范俊张鹏
编辑: 陈冀康
分类: Node

图书目录:

详情

本书基本分为两部分,第一部分概述Node.js 、MongoDB和Backbone.js(本书讲述的核心技术),第二部分是如何使用这些工具去构建一个具有社交网络风格的网站。如果是刚开始学习,建议先从第一部分获取一些背景知识,然后在第二部分深入学习。如果你已经熟悉Javascript,可以直接跳过第一部分,会发现第二部分中的例子也是可以理解的。

图书摘要

版权信息

书名:Node应用程序构建——使用MongoDB和Backbone

ISBN:978-7-115-34629-2

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    [美] Mike Wilson

  译    林 冀 范 俊  张 鹏

  责任编辑 陈冀康

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


Copyright© 2013 by O’Reilly Media, Inc.

Simplified Chinese Edition, jointly published by O’Reilly Media, Inc. and Posts & Telecom Press, 2013. Authorized translation of the English edition, 2013 O’Reilly Media, Inc., the owner of all rights to publish and sell the same.

All rights reserved including the rights of reproduction in whole or in part in any form. 本书中文简体版由O’Reilly Media, Inc.授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


Node.js是一套用来编写高性能网络服务器的JavaScript工具包。Backbone.js是面向客户端的JavaScript框架。MongoDB是一种NoSQL的数据库。三者结合使用,可以构建出高效的Web引用。

本书分为两部分,共10章。第一部分包括第1到4章,概述了Node.js 、MongoDB和Backbone.js的核心技术。第二部分包括第5章到第10章,介绍如何使用这些工具去构建一个具有社交网络风格的网站。如果是刚开始学习,建议先从第一部分获取一些背景知识,然后在第二部分深入学习。如果你已经熟悉JavaScript,可以直接跳过第一部分,会发现第二部分中的例子也是可以理解的。

本书可以作为学习和掌握Node.js、Backbone.js和MongoDB的实践教程,也适合对这几种技术感兴趣的读者阅读参考。


Mike Wilson 曾有幸在世界上一些最大和最有影响力的品牌工作,其中包括迪斯尼、微软和麦当劳。他具有多年的web开发经验,从小型企业网站到能够容纳百万玩家的大型MMO服务器集群都能够设计和构建。在他空闲的时间里,Mike维护着他的个人博客(http://www.alwaysgetbetter.com/)并参与到一些论坛中去,对新兴的软件和框架进行试验。Mike与他的妻子和三个孩子住在温哥华。

本书的封面上的动物是小灵猫(Viverricula indic),在南亚和东南亚以及印度尼西亚群岛都有发现。这种动物是以自卫过程中会产出厚黄麝香气味的物质命名的。

小灵猫身材修长,能够敏捷爬树,没有竖起的鬃毛,生活在洞里岩石上和毛茸茸的位置。在夜间,独来独往,通常它会栖息在树上;也就是说,它会爬树,并待在那里。然而,当狩猎时,它会在地面水平位置。灵猫基本上是杂食的包括蜥蜴,鼠类,鸟类,昆虫,甚至是鸡蛋。在人工饲养下,它很容易驯服,给它喂小动物,它会像猫一样灵巧。

在小灵猫身上有一排排黑色的斑点和尾巴上的条纹搭配上灰色或黄褐色。它的腿、耳朵和嘴巴也是黑色的。

灵猫(也称果子狸)产生的麝香是非常珍贵的香味和香料的稳定剂。雄性和雌性狸猫身体上的腺体都会分泌强烈的气味。人们为获得狸猫的肉而捕猎它,将它的皮肤净化后入药。


Mike Wilson曾有幸与世界上一些最大和最有影响力的品牌一起工作,其中包括迪斯尼、微软和麦当劳。他具有多年的Web开发经验,从小型企业网站到能够容纳百万玩家的大型MMO服务器集群,他都能够设计和构建。在空闲的时间里,Mike维护着他的个人博客(http://www.alwaysgetbetter.com/),并参与一些论坛讨论,对新的软件和框架进行试验。Mike Wilson与妻子和三个孩子住在温哥华。


Google在2008年发布了第一个版本的V8 JavaScript引擎时,兴奋就像安静波澜,在开发者社区荡漾开来。第一次(承诺),我们能够在客户端和服务器都使用JavaScript进行编程:使用一种语言来控制一切。Web应用程序已经开始变得更像桌面并且复杂程度也在膨胀,所以减少语言数量的依赖这个想法有利于使技术开放和透明,推出更加令人兴奋和不断突破的应用程序。

Ryan Dahl就是一个看到了新的机会的开发者,他没有浪费时间,马上将他原来写的非阻塞套接字库转换到新的V8引擎上,导致了Node.js的诞生。他发布的技术已经让原来荡漾着的兴奋变成一次重大范式变革,对于实时响应的应用程序的兴趣到达了高峰。Node.js不仅仅是一组套接字函数的集合,它提供了一个框架处理异步I/O,以全新的事件驱动编程模式作为基础。

网上的情况在过去的几年中已经快速发生改变,没有任何迹象表明会放缓。“社交”网络的爆发对我们来说意义重大:越来越多的人在线,已经不只是技术用户。互联网是所有人的,在这个新的空间里,赢家将是那些明白如何让在线体验温暖而人性化,真正让人与人之间联系起来的公司。

使用JavaScript来连接系统提供了一个优势,因为你可以快速从处理与个人用户交互的前端Web堆栈转换到处理后端的数据存储,以及之间的所有网络管道。你将能够把系统真正模块化;每个部分都是可插拨的,可以部署到资源最合适它的地方。不同于以前,你创建的应用程序将可以与用户群共同成长、共同呼吸。

本书的读者应该了解网站和网络应用是如何组织在一起的。为了保持对核心技术的专注,本书略过“为什么”构建Web应用程序,而关注“如何”构建。

要完全理解书中的示例,需要一些JavaScript的知识。这些示例会进行透彻的解析,但是以前的知识能够帮助读者理解编写过程中做出的编程决策和背后的故事。

许多开发者使用NoSQL数据库是从关系型数据库系统转过来的。这本书并没有假设读者熟练掌握数据库设计,我详细讨论了在整个数据库架构阶段做出的设计决策的缘由。MongoDB对于SQL的概念是友好的,这是选择它作为这个项目数据存储的主要动机。

在本书的最后一部分,我将走出第一和第二部分中纯JavaScript环境的构建,讨论如何选择支持的工具和技术。不要求读者对其他的语言(比如Scala、Java、PHP和Bash脚本编程)有深刻的理解,因为深入探索这些概念超出了本书的范畴,所以我鼓励使用这些示例作为跳板,进行进一步研究。

这本书基本分为两部分,第一部分概述Node.js、Backbone.js和MongoDB(本书讲述的核心技术),第二部分是如何使用这些工具去构建一个具有社交网络风格的网站。如果是刚开始学习,建议先从第一部分获取一些背景知识,然后在第二部分深入学习。如果你已经熟悉JavaScript,可以直接跳过第一部分,会发现第二部分中的例子也是可以理解的。

下面是本书的组织结构。

第一部分 Node.js、Backbone.js和MongoDB简介

第1章 介绍和总览

本章介绍了JavaScript和贯穿全书探讨的一些核心概念。

第2章 Node.js

本章介绍了Node.js,并引导你开始第一个独立的应用程序。当你熟悉关键模块后,你会用它来建立一个完整的实时应用。

第3章 Backbone.js

接下来,您将探索Backbone.js如何使得JavaScript在浏览器上的编程更像是构建传统应用程序而不是网站。我们也会遇到维护基于JavaScript项目中的一些问题,引入模板将可视的HTML布局与功能性的JavaScript应用代码分离开。

第4章 MongoDB

喜欢MongoDB是因为它可以快速和简单的搭建,易于接口,并与Node.js应用语言相通。在这一章我们将着眼于如何做基本的查询和数据处理,以及当MongoDB使用增长时复杂随之增加,这些情况也是需要考虑的。

第二部分 建立社交网络

第5章 创建项目

如何构建项目并将项目中的文件组织在一起是面临的一个大问题。在这一章中配置Node.js和Backbone.js形成这个网站,为其余的代码奠定基础。

第6章 认证

在使用应用程序之前,你需要创建账号并登录。在这一章中解释了如何从数据库中获取用户,并且一旦拥有他们的数据,如何确保数据的安全。

第7章 用户界面

在基本结构和登录功能完成之后,这一章引导你建立网页,包含所有展现给用户的内容。这里我们将详细介绍模板和Backbone.js的使用,集成访问控制和Node.js。

第8章 交朋友

联系人列表就是这个网站背后的社交部分。在这一章中,你将学习到如何在列表中添加和删除联系人,将数据去规范化,存放到MongoDB中。对于一个来自关系型数据库环境的来说,这一章是很值得阅读的。

第9章 聊天

这一章在第8章创建的联系人列表的基础上,利用Socket.io添加了实时聊天的功能。你和朋友之间收发消息不需要重新加载页面。

第10章 实时互动

最后,我们将回顾书中构建的用户界面,利用Socket.io进行扩展,就像聊天列表一样。这将为网站增加活力,让用户及时知道联系人的上线和下线,将所有共享的消息空间变为可以交互的聊天室。



互联网已经成为发展最快的技术领域之一,它还在加速。对于希望通过编写软件来获得收入的人来说,这既是好消息,也是坏消息。今天,优秀的开发人员拥有难得的机会,可以做他们喜欢的事,拓展视野,不断进步,并从工作中得到更大的满足,只要他们愿意付出必要的努力,去理解海量的、快速增长的知识。

精彩的职业生涯是有代价的。作为一名软件开发者,你必须不断寻找下一个优秀的工具,来帮助你更多、更好、更快地实现梦想。你在10年后面对的东西,与今天面对的东西会完全不同。本质上说,你需要多次再培训自己,才能保持好的状态。

马尔科姆·格拉德威尔(Malcolm Gladwell)在他2008年所著的《Outliers》一书中指出,专业水准的融汇贯通需要10 000小时的努力。即使是天才也需要投入时间来收获成功,平庸者和精湛者之间的差异归结于个人实践经验的多少。阅读本书这样的书籍,能让你成为精湛者。现在你正在花费额外的时间,接触这门前沿的手艺。未来即将到来,你会首先获得它的好处。

Node.js已经将一大批软件开发者引入了面向事件编程。无论你的技术背景如何,只要有开放的心态,放下对JavaScript的偏见,就会领悟到在这个疯狂应用多线程的世界里,单线程编程是多么强大。更重要的是,你会更欣赏事件处理,在其他编程语言中处理多线程问题时,也会有所帮助。

JavaScript是一种独特的编程语言,有时会被误解,现在它在开发人员的工具箱中终于得到了应有的地位。由于开发JavaScript应用程序的工具集不断完善和成熟,你会看到全球范围内这种编程语言的重要性在持续增长。

本书将手把手指导你搭建一个社交网络,类似于LinkedIn、MySpace或Facebook。使用Node.js,Backbone.js和MongoDB作为工具,你将学会如何创建一个快速响应的应用,并且可以扩展到几百万用户。

由于是例子,本书中介绍的许多组件会走捷径,使用Node或MongoDB提供的内建方法,来展示某项功能,但在“真正”大型的部署中是不合适的。如果出现这样的捷径,我会给出特别提示,并探讨如何转向更具扩展性或更容易修改的结构。本书的挑战是在清晰性和构建真正实用的应用之间取得平衡。

什么是社交网络?“社交网络”这个简单的词组似乎传达了很多意义(在行为科学领域,确实如此),让我们逐词解读,并应用于因特网。“网络”是互联的一组系统,它可以是任何东西,从遍布全国的高速公路网,到学校实验室里的一排计算机,或是名片盒里的专业联系人。“社交”这个词指的是生物体的交互(如动物或人),以及它们作为群体的存在。所以社交网络在这里指的是一群互联、互动的人。

在社交网络里,人的因素高于一切。在构建任何软件时,如果不首先(并且持续)考虑最终用户(不论是客户、教授还是你自己),就针对某一特定功能或目标进行开发,这就是不负责任。要抵制为了技术的缘故而继续编程之路的冲动,直至你能看清楚工作的最终目的。

我们说打造一个社交网络时,当然不可能是打造这里定义的社交网络。你要创建的是一个论坛,一条道路,让社交网络生根成长。系统的每一项功能都为这一目标服务,消除用户的障碍,提供足够的功能来推动、鼓励和促进沟通,而没有过多的修饰。这是一条充满困难的道路,但也是区分伟大和平庸的产品的唯一途径。

本书多处提到并使用“模型—视图—控制器(MVC)”设计模式,进行服务器端和前端编程。有人认为,MVC在Web上是随着Ruby on Rails的增长而流行的,但它最早是在20世纪70年代为Smalltalk平台开发的。

MVC的主要作用是将系统拆成3个弱耦合的部件。

模型:包含了要读取或操作的数据的一种结构。

视图:用户与模型产生互动的界面。

控制器:在视图和底层模型之间代理用户操作。

模型和控制器通常成对出现。在本书中,控制器的工作可作为用户和模型之间来回传递消息的合约。虽然一个控制器可以操控多个模型,但这样做不好,我们建议一个控制器对应一个模型。

视图不一样。就像现实生活中一样,软件往往提供多种方式来展现同一信息。例如,音频的文字版本包含了和原始内容一致的信息,但它的内容传播更容易、更方便。因特网到处都是这样的例子:很多网络服务的数据展现同时采用JSON和XML,用两种不同的格式提供相同的信息。

Node、Backbone和MongoDB让你使用单一编程语言,专注于应用逻辑,最终降低系统各部分之间的连接次数。你会看到这是一种引人注目的编程方式,因为客户端UI、后端服务器逻辑和数据库持久之间的界限模糊了,几乎形成一个生动的系统。随着实时网络逐渐进入生活,情况就更清楚了。数据在各个应用中舞动,甚至经过多个用户之手,所有事情就像一齐发生在单个过程中。

有些缺陷是需要预先避免的。虽然连接方式很强大,使用同一种方言,但是在底层,你的工作仍然是跨浏览器、服务器和数据库的编程。有些JavaScript开发范式着眼点略有不同,这取决于它们的主要目标是服务于UI(如在浏览器中使用的Backbone)、验证(如在服务器端常用的Node)或持久(如本书中提到的MongoDB)。你需要时刻保持警惕,注意数据要去哪里,是否阻塞你自己的进程,如何监听进出的事件并做出反应。这可能是一个挑战,但就像其他有许多灵活部分的系统一样,在实验中会有许多有趣的收获。


今天的互联网不同于20世纪90年代的互联网。在以前,用户和一个网站之间的交互基本上属于信息消费。Web服务器生成大量静态网页,用户在页面之间穿梭。当然也有动态元素,但互动的信息流主要是限于请求和应答。多年的研究都集中于优化客户端—服务器的信息流,可以肯定地说目前对这方面的理解很透彻。

大约在IE6开始出现时,一个微妙而根本的转变开始占据上风。因特网用户变得越来越适应和内行,电脑变得更为强大,宽带连接开始变得常见。人们使用因特网不再是主要为了信息和交易,而是在社交和娱乐上花更多时间。因特网现在是媒体频道,但与之前的电视、广播和报纸不同。

现在互联网络用户不是消费数据,而是产生难以想象的大量数据。Web服务器和浏览器作为信息消费者的传统观念仍然存在,但了解这一点仅仅看到了信息发布者很少一部分能力。现在的重点是使人控制他们的体验,并借助他们创造的数据去实时改变、改进和提高这些体验。这是一个崭新的世界,网络服务器和程序员不再是体验的来源,而是促进者。

Node.js是转向“因特网即体验”范式的新型技术之一。

如果你没有安装过Node.js,那么首先你得安装它。你可以从Node项目主页(http://nodejs.org)下载到适合自己的操作系统的安装包。主页提供了用于UNIX、Mac和Windows的二进制安装包。如果你真心喜欢冒险,可以从Node的GitHub版本库中找到链接,安装一个开发快照版。在撰写本书时,Node的稳定发行版本是。

Node提供了一个JavaScript运行时环境,你可以在任何时候使用命令提示符或终端窗口,输入node。考虑到本书的目的,你需要运行JavaScript源文件,而不是直接输入代码。要运行一个JavaScript文件,使用Node命令带一个参数,比如:node filename.js。

Node采用包管理工具npm进行管理,它让你在你的代码中引用第三方的库。包管理是使用Node的很重要的一个方面,没有它,你必须从头开始编写所有的应用,重新发明一些常见问题的解决方案,而这些问题已经被其他数以百计的开发者解决并共享了。

要用npm安装一个库,只要用库名作为参数来运行npm,比如:npm install async。

npm十分有用,不仅仅是进行简单的安装:它帮助你打包应用,控制库版本,甚至与朋友分享项目。在本书第二部分,我们将深入探讨npm。现在只要说你和npm将成为亲密的朋友。

本书中应用程序大量用到Express框架。依赖于Connect HTTP服务器框架,Express提供了视图渲染和一种描述路由的语言。

要安装Express,只要在工作目录中使用npm:npm install express。

例2-1利用Express构建了一个简单且非常实用的服务器。首先,通过调用express库中的express()函数对app变量初始化。require命令指示Node导入express库,并把它分配给一个局部变量,从而将它的功能提供给当前命名空间。

例2-1 一个Express小应用

应用初始化时,定义了3个路由。

/stooges/[name]

期待一个stooge(配角)的名字作为输入。

/stooges/

如果上一个路由提供的名字未找到,给出反馈信息。

/

一个默认的路由,用于访问应用程序的主页。

在第1个路由,Express会比较提供的配角名称是否为“larry”、“curly”或“moe”,并打印信息。在下一个路由中,Express显示一条消息说明没有找到配角名称。第3个路由中,显示默认的“hello world”。

等一下,第1个路由中的next参数是从哪里来的?它又是什么?实际上,next是指一个函数。next命令指示Express尝试处理匹配当前请求的下一个路由。在这个例子中,输入URL/stooges/ 会被第一个路由(/stooges/:name?)处理,而不是被第2个路由(/stooges)处理。由于没有提供名字,switch语句逻辑会跳转到默认情况下,此时next()函数会被调用。下一个路由(/stooges)包含了预期的响应。

:name参数之后的问号表明name是一个可选的输入,即使不提供name,这个路由也将被加载。

警告

你会看到很多在线资源,用express.createServer()来实例化app,而不是用express()。函数createServer()已被弃用,尽管它可能在相当长一段时间内仍可使用,但最好避免使用它,让你的应用程序尽可能未来也能用。

在switch语句中,使用了一个三元操作符作为缩写的if/else语句:name ? name. toLowerCase() : ''。这相当于一个很长的代码块,检查变量name是否存在,如果存在,返回小写的字符串,否则返回一个空字符串。

模板让你将展现信息从程序代码中分离出来,使你的项目文件更易整理,并渲染出复杂结构的网页。虽然本书主要关注用纯JavaScript来创建和显示视图,但有时候你也会想用Express的模板功能来生成网页,或者只是为了更容易在一个网页中引导所有的JavaScript文件。我选择Jade作为引擎,因为它在概念上类似于CSS,能产生清晰、简洁的代码。

要安装Jade模板引擎,在工作目录中使用NPM命令。

例2-2在例2-1的基础上增加了Jade模板支持。3个路由都使用了res.send代替直接在屏幕上打印文字。Express被告知以.jade作为后缀的文件来渲染内容:要么用stooges.jade模板来渲染配角名字列表(或没有名字),要么用默认的index.jade来渲染网站的根。

例2-2 使用Jade模板的Express应用

另外新增的是包含app.set('views'...)的3行代码。这个命令告诉Express所有视图都存放在命名为“views”的目录下,是相对于代码文件运行(-dirname)的下级目录。

虽然Jade是用来渲染视图的,但你可能已经注意到,代码中并没有提到或实例化Jade。这是因为Express渲染命令会负责加载任何需要的模板模块,在这个例子中是Jade。如果你没有安装Jade,你的应用程序将会在进行页面渲染时停止运行,并抛出调用栈。

例2-3展示了使用Jade的整个页面布局。这是围绕“真正”页面的部分,它们是网站每一个页面上的标题信息,开放的标签和元数据。body标签将包含单个视图渲染的布局,Express渲染模板时将会包含这个布局。

例2-3 Jade布局(layout.jade)

!!! 5

警告

缩进在Jade模板中具有重要含义。如果你从一个PDF文件中复制粘贴这段代码,空格缩进可能无法正确地保留,这取决于你使用的软件。

第一行“!!! 5”表明文档类型是HTML5。也可以写成doctype html,但谁高兴打那么多字?

例2-4中包含的模板应该保存在views/index.jade中。它包含网站根内容:没什么消息比一个“hello world”更简单。这个模板的第一行扩展了例2-3中创建的layout.jade模板,这将导致用户的网络浏览器渲染布局的内容。因为h1标签嵌套在模板的block content元素中,Jade知道它应该在布局中的block content被定义后再被渲染。

例2-4 Jade风格的索引主页(index.jade)

你可能会注意到,例2-3的布局还包含一个block元素称为scripts,它没有被index模板使用。这个脚本块在网页浏览器中显示为空白。可以在你的模板中添加或删除任何block内容,为页面布局留下极大的灵活性。

例2-5在Jade模板中引入了条件逻辑。如果一个stooge变量被传递到模板,它将显示出这个配角的名字,否则它将显示一般的“没有找到”消息。

例2-5 Jade风格的新stooges页面(stooges.jade)

事件是Node.js的活力之源,实际上也是JavaScript本身的活力之源。其他语言在多个并发线程中处理工作流,每个线程都将大部分时间花在等待阻塞的I/O操作上,如磁盘读取、数据库操作或通过网络获取信息。但JavaScript总被认为是一个基于事件的编程模型。早期的事件很简单,如一次鼠标点击、一个页面加载或一次表单提交。更晚期的用法包括完成一次数据库写入,或从磁盘读入文件的内容等事件。

JavaScript利用回调,通过另一种方式来解决问题。程序员编写称为“回调”的特殊函数,让它与特定的事件挂钩,在符合条件时执行,而不是管理长时间运行的进程。例2-1和例2-2的路由例子说明了这一点:Node.js为每个URL设置了特定的响应,然后只在Web浏览器访问这些路由时执行相应的代码。

Node.js包括一个专门的事件库可以供你准备自定义事件。假设你有一个网络应用程序,已经开放给其他开发人员。如果他们想扩展你的工作,有两种选择:基于你的代码创建一些原型函数,并重写所有行为不同的函数,或者直接修改你的代码,构建他们需要的特性。事件给出了第三种选择:在你的代码的特定位置触发一个事件,让所有监听者知道动作已发生,并注入他们自己的行为。

例如,如果你的应用程序包含一个登录功能,你可能有一个OnLoggedIn事件。后继的开发人员可以添加一个监听器来提供额外的功能,如连接到社交网站收集所有与登录者相关的新闻。

例2-6 创建与处理应用程序事件


例2-6展示了怎样将3个无关的事件onApplicationStart、onApplicationRun和onApplicationStop串在一起,产生下面的输出。

在mainLoop函数执行之前,调用eventEmitter的on方法注册了ApplicationStart、ApplicationRun和ApplicationStop事件。这为每一个事件增加了一个事件监听器:从现在起,只要有事件发生,都会检查这些监听器是否匹配,匹配的回调函数将被执行。

屏幕输出突出了Node.js的一个重要特征:所有工作都在单个线程中进行。当事件发生并由回调响应时,调用方法会暂停直到回调执行完毕。这很重要,因为如果在回调期间发生了消耗大量运算资源的事情,原始函数将不会继续执行,直到全部工作完成。所以这个例子的执行遵循以下路线。

1.运行mainLoop,触发ApplicationStartEvent。

2.运行回调onApplicationStart。

3.继续执行mainLoop,触发ApplicationRun。

4.运行回调onApplicationRun。

5.继续执行mainLoop,触发ApplicationStop。

6.运行回调onApplicationStop。

7.回到mainLoop的执行,接下去没什么可做的,停止。

Socket.io是你的朋友。它将消除制作实时网络应用程序时的乏味工作,处理所有跨浏览器兼容的问题,在你的后端Node服务器和前端JavaScript客户端之间,留出干净、简单的JavaScript接口。这是一个令人激动的库,因为作为一个程序员,它让你专注于单一脚本语言的程序代码,消除数据和最终用户之间的网络障碍。

要安装Socket.id,就用npm。

例2-7为网站添加了实时聊天功能,它创建了一个Socket.io对象,并将其附加到http.Server上,在Express之前。在接到浏览器的socket连接时,Socket.io触发应用内的一个回调函数,向连接用户发出任意的一段欢迎消息。sendChat函数是为了方便而创建的;给定标题和内容,它使用Socket.io的emit命令发送一段JSON数据给连接的socket。因为它在回调函数之内,所以对所有socket级别的事件是可见的,但对应用的其他部分是不可见的。

例2-7 为Express服务器添加实时聊天功能


socket.on('chat'…)这行代码创建了一个事件回调,每当连接的用户往socket发送消息时,就会执行。这里没有太多功能,服务器只是将用户发来的消息直接显示给他们。

为了给这个例子增加点活力,我已经将一个JavaScript的setInterval函数与其回调函数包含了进来,每隔5秒钟,它会向连接的客户端随机发送3个配角的一句口头禅。

在例2-7中,Express服务器的实例化和之前的例子不同。它不是让Express对象直接监听传入的连接,而是先通过http.createServer(app)函数附加在http.Server中,得到的服务器对象再监听进入的连接。在幕后,Express的listen命令做同样的事而不暴露http.Server。采用这种方式,你要暴露http.Server,以便让Socket.io连接到它。

例2-8的聊天布局在block scripts中加入了内容,在浏览器中渲染时,它在HTML内容中加上了Socket.io的功能。Socket.io使某些文件可供下载,这就是为什么你可以包含对/socket.io/socket.io.js的脚本引用。JavaScript文件socket.io.js包含了浏览器连接到socket服务器所需的全部功能,它还包含回退机制,为过时的、不支持Web socket的浏览器提供类似socket的功能。

例2-8 聊天页面的Jade模板(chat.jade)

一旦提交按钮被激活,Socket.io会发出聊天框的内容。在从网络服务器接收聊天事件后,Socket.io会把传入的消息内容替换到聊天显示窗口(div#chat)。重要的是,要注意到socket事件和函数不论用在客户端上还是网络服务器上都是完全相同的。这让你为整个应用程序提供了一个干净的通信联系,无需担心传输或接收的数据需要转换。

Node引发了服务器端JavaScript编程的巨大兴趣,更别提对一般JavaScript的影响了。但这不是JavaScript第一次脱离浏览器作为工具,实际上,JavaScript在网景公司的浏览器中首次亮相之后不久,该公司发布的一个Web服务器就包含了该语言。不到一年后,微软的因特网信息服务(IIS)服务器软件也开始支持服务器端JavaScript(他们的方言称为JScript)。大约在同一时间,网景打算使用Java编程语言重写他们的旗舰Web浏览器,该项目最终产生了Mozilla的Rhino JavaScript引擎。

如果这听起来像是一个快速碎片化的市场,请想象一下试图为一个现有服务器产品编写JavaScript代码,然后在其他地方重用同样的代码。如果你的应用足够小,你或许可以通过一些修改对付过去。任何正常大小的应用程序很快会发现,这时需要调用外部库和模块化组件,否则最后将得到一个乱成一团、无法维护的几千行脚本代码的大文件。每个服务器都有不同的方法来划分应用代码,但没有统一标准。一旦选用了一种,你就被套牢了。

情况并没有好多少,虽然今天在代码开发标准化、命名空间保护、对象创建和模块化方面已经取得了重大进步。CommonJS旨在为脱离浏览器的JavaScript提供一套标准规范,其中许多已经被Node采用。如果你刚开始使用Node,而你的应用程序已经大到不合适放在一个文件中,那么你必须知道,你的应用无法使用外部文件中声明的变量,除非显式地使用exports关键字使它们可见。

例2-9展示了一个简单的Node.js模块,它暴露出一个函数:getFlagWidth,用于计算美国国旗的法定宽度,宽度必须1.9倍于国旗的高度;这个比例存储在名为FLAG_WIDTH的变量中。函数getFlagWidth获取高度值并乘以宽高比例,为给定的国旗高度产生对应的宽度。

例2-9 计算国旗宽度的模块

如果你在应用中包含这个文件,你将能够访问getFlagWidth函数,它使用exports关键字暴露接口,而不是FLAG_WIDTH变量。FLAG_WIDTH可以认为是一个“私有”变量,只能在该模块的上下文中访问,而不能在整个应用范围内访问。


相关图书

Node.js 后端全程实战
Node.js 后端全程实战
Node学习指南 第2版
Node学习指南 第2版
Tomcat内核设计剖析
Tomcat内核设计剖析
写给PHP开发者的Node.js学习指南
写给PHP开发者的Node.js学习指南
Node学习指南
Node学习指南
Node.js入门经典
Node.js入门经典

相关文章

相关课程