官网给Node.js吓得定义是:“一个搭建在Chrome V8 JavaScript运行时上的平台,用于构建高速、可伸缩的网络程序。Node.js采用的事件驱动、非阻塞I/O模型,使它即轻量又高效,并成为构建运行在分布式设备上数据密集型实时程序的完美选择。”
Node为服务端JavaScript提供了一个事件驱动的(用事件轮询)、异步的平台。
Nginx跟Apache一样,是个HTTP服务器,但它用的不是带有阻塞I/O的多线程方式,而是带有异步I/O的时间伦璇。因为这些设计上的选择,Nginx通常能处理更多的请求和客户端连接,它因此编程了响应能力更强的解决方案。
在Node中,I/O几乎总是在主事件轮询之外进行,是的服务器可以一直处于高效并且随时能够做出响应的状态。这样进程就更加不受I/O限制,因为I/O延迟不会拖垮服务器,或者像在阻塞方式下那样占用很多资源。
DIRT:它表示数据密集型实时(data-intensive real-tiem)程序。
因为Node自身在I/O上非常轻量,它善于将数据从一个管道混排或者代理到另一个管道上,这能在处理大量请求时持有很多开放的选择,并且只占用一小部分内存。它的设计目标是保证响应能力。
看来Node真的就是玩I/O的,我得再把fs和steam玩深点才行。
- 平台与架构: Node是JavaScript程序的平台,不要把它跟框架混淆。很多人误把Node当做JavaScript上的Rails或Django,实际上它更底层。
Node在数据流和数据流动上很强大。你可以把数据流堪称特殊的数组,只不过数组中的数据份分散1在空间上,而数据流中的数据是分散在时间上的。通过将数据一块一块地传送,开发人员可以每收到一块数据就开始处理,而不用等待所有数据都全了再做处理。
可读和科协流可以连接起来形成管道,就像Shell脚本中用的|
(管道)操作符一样。这是一种高效的数据处理方式,只要数据准备好就可以处理,不用等着读取完整个资源再把它写出去。
Node在多个平台默认提供了DIRT方式,包括各种Windows和类UNIX系统,底层的I/O库(libuv霸王龙)特意屏蔽了宿主操作系统的差异性,提供了统一的使用方式,使得程序可以在多个设备上轻松移植和运行。
这章是真实操,貌似记的不多。
-
聊天室程序
- 提供静态资源文件
- 在服务器上处理与聊天相关的消息
- 在用户的浏览器中处理与聊天有关的消息
-
commonJS中package规范说明网址
-
Socket.IO提供了开箱即用的虚拟通道,所以程序不用把每条消息都向已连接的用户广播,而是只向那些预定了某个通道的用户广播。Socket.IO其实也是个事件发生器发射器(Event Emitter)。
-
聊天室程序需要处理以下场景和事件:
- 分配昵名;
- 房间更换请求;
- 昵名更换请求;
- 发送聊天消息;
- 房间创建;
- 用户断开连接。
关于require和同步I/O require是Node中少数几个同步I/O才做之一。因为经常用到模块,并且一般都是在文件顶端引入,所以把require做成同步的有助于保持代码的整洁、有序,还能增加可读性。但在程序中I/O密集的地方尽量不要用require。所有同步调用都会阻塞Node,直到调用完成才能做其他事情。比如你正在运行一个HTTP服务器,如果再每个进入的请求上都用了require,就会遇到性能问题。所以通常都只在程序最初加载时才使用require和其它同步操作。
- 关于
module.exports
和exports
导出的究竟是什么- 最终在程序里导出的还是
module.exports
。exports
只是对module.exports
的一个全局引用,最初定义为一个可以添加属性的空对象。所以exports.myFunc
只是module.exports.myFunc
的简写。 - 所以,如果把exports设定为别的(引用型),就打破了module.exports和exports之间的引用关系。可是因为真正导出的是module.exports,那样exports就不能用了,因为它不再指向module.exports了。如果你想维持那个链接,可以像下面这样让module.exports再次引用exports:
module.exports = exports = Currency
。
- 最终在程序里导出的还是
Node的异步回调惯例 Node中的大多数内置模块在使用回调时都会带两个参数:第一个是用来存放可能发生的错误,第二个是放结果的。
- 在Node中优化回调的方法
- 创建中间函数以减少嵌套
- 通过今早返回减少嵌套