学习Node的书单早早就列了出来,接下来就是一步一步的进行学习。

  • 《Node.js开发指南》
  • 《Node与Express开发》
  • 《Node.js实战》
  • 《深入浅出Node.js》
  • 《Node.js+MongoDB+AngularJS Web开发》

    《Node.js开发指南》学习笔记一

1. 调试Node

supervisor

如果你有PHP 开发经验,会习惯在修改PHP 脚本后直接刷新浏览器以观察结果,而你在开发Node.js 实现的HTTP 应用时会发现,无论你修改了代码的哪一部份,都必须终止Node.js 再重新运行才会奏效。这是因为Node.js 只有在第一次引用到某部份时才会去解析脚本文件,以后都会直接访问内存,避免重复载入,而PHP 则总是重新读取并解析脚本(如果没有专门的优化配置)。Node.js的这种设计虽然有利于提高性能,却不利于开发调试,因为我们在开发过程中总是希望修改后立即看到效果,而不是每次都要终止进程并重启。

安装supervisor,使用npm模块管理器,npm install -g supervisor,然后,使用supervisor app.js来启动app.js,当代码被改动的时候,脚本自动重启。

2. Node异步编程

  • 同步式I/O(Synchronous I/O)就是阻塞式I/O(Blocking I/O)
  • 异步式I/O(Asynchronous I/O)就是非阻塞式I/O(Non-blocking I/O)

阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程所使用的CPU 核心利用率永远是100%,I/O 以事件的方式通知。在阻塞模式,多线程往往能提高系统吞吐量,因为一个线程阻塞时还有其他线程在工作,多线程可以让CPU 资源不被阻塞中的线程浪费。而在非阻塞模式下,线程不会被I/O 阻塞,永远在利用CPU。多线程带来的好处仅仅是在多核CPU 的情况下利用更多的核,而Node.js的单线程也能带来同样的好处。这就是为什么Node.js 使用了单线程、非阻塞的事件编程模式.

同步方式读取文件

var fs = require('fs');
var data = fs.readFileSync('file.txt' , 'utf-8');
console.log(data);
console.log('end.\n');

异步方式读取文件

var fs = require('fs');
fs.readFile('file.txt' , 'utf-8' , function(err,data){
    if(err){
        console.log(err);
    }else{
        console.log(data);
    }
});
console.log('end.\n');

3. 模块与包

Node.js中模块和包没有本质的区别,都是一个文件。两个概念时常混用。一个文件可以是一个模块,一个模块也可以写在一个文件中。

3.1 模块

  • Node的模块是单次加载,比如下面的例子。

    //modele.js
    var Name;
    exports.setName = function(name){
        Name = name;
    }
    exports.sayHello = function(){
        console.log("Hello " + Name);
    }
    
    
    //single.js
    var hello1 = require('./module');
    hello1.setName('zhangsan');
    var hello2 = requier('./module');
    hello2.setName('lisi');
    
    
    hello1.sayHello();
    

    你会发现结果会是Hello lisi,因为hello1,hello2是同一个实例的不同引用而已。

  • 导出对象的函数 exports.hello = hello

  • 导出对象 module.exports = hello

3.2 包

包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供了一些固定接口的函数库。

包的安装分为全局模式以及本地模式,本地安装只是将包安装在了当前目录的node_modules子目录下;而全局模式安装的时候会将包安装在了系统目录下,比如/usr/local/lib/node_modules/,不一定是这个目录,这取决于你的系统以及node的安装目录。

大部分情况下使用全局模式安装的包会自动定义到PATH环境变量中,也就是可以直接通过命令行还运行。然而使用全局模式安装的包却不能在Javascript文件中使用require获取到。

总而言之,当我们要把某个包作为工程运行时的一部分时,通过本地模式获取,如果要在命令行下使用,则使用全局模式安装。

《Node.js开发指南》学习笔记二

HTTP模块可是说是Node里面最基础最核心的模块。也是Node区别于其他语言的一个特点,使用Node搭建网站无需再配置Http服务器,HTTP模块就提供了服务。

通过HTTP模板可以轻松搭建HTTP服务器以及客户端,下面记录了一些重要的概念。

1. HTTP服务器

了解过Node基本上就能写出下面的Hello,World代码。

var http = require('http');
http.createServer(function (req,res){
  res.writeHead(200 , {"Content-Type" : "text/html"});
  res.end("hello,world!");
}).listen(8888);
console.log("Your server is started @ http://localhost:8888");

上面这段代码是学习Node最开始都要接触的所谓的Hello,World!。下面的笔记或许能帮助做进一步了解。

  1. http.server 服务器对象,继承至EventEmitter。

    • createServer()函数返回一个http.server对象
    • 请求到来时,request事件被触发
    • req以及res两个参数分别是http.ServerRequesthttp.ServerResponse对象的实例
    • TCP连接建立,connection事件被触发,提供scoket参数为net.Socket实例
    • 服务器关闭时,close事件被触发。

    根据上面的笔记,可以进一步了解HTTP服务器创建的细节,那么上面的那段代码就可以写成下面这个样子。

    var http = require('http');
    var server = new http.Server();
    server.on('request',function(req,res){
      res.writeHead(200,{"content-Type" : "text/html"});
      res.end("Hello,World!");
    });
    server.listen(3000);
    console.log("Server is started @ http://localhost:3000");    
    

    显式写出http服务器的代码,证明对于Node的事件驱动的了解又深入了一步。

  2. http.ServerRequest HTTP请求信息对象

    • HTTP请求:请求头(Request Header)和请求体(Request Body)
    • 当请求体数据到来时,触发data事件,事件提供chunk参数,表示接受到的数据
    • 数据传输完成,触发end事件
    • 用户请求结束,触发close事件
  3. http.ServerResponse 服务器响应对象

    • 返回客户端的信息,决定用户最终看到的结果。
    • 返回响应头,响应内容以及结束内容
      • response.writeHead(statusCodes, [Headers])
      • response.write()
      • response.end()

2. HTTP客户端

在Node中通过HTTP模块也可以实现客户端的功能,主要通过两个函数http.requesthttp.get作为客户端向HTTP服务器发送请求。

  1. http.request(options, callback) 发送请求 请求参数:options,包括host、post、method、path、headers 请求内容:contents,

  2. http.get(options, callback) 发送Get请求,该方法是上面的简化版。

  3. http.clientRequest 客户端请求对象 由http.requesthttp.get返回产生的对象,表示一个已经产生而且正在进行中得HTTP请求。如:var req = http.get()http.ClientRequesthttp.ServerResponse一样也提供了writeend函数,用于向服务器发送请求体,通常用于POSTPUT等操作。

  4. http.clientResponse 客户端响应对象 与http.ServerRequest相似,都有3个事件dataendclose,分别在数据到达,数据结束,断开连接时触发事件。http.clientResponse还提供了几个特殊的函数。

    • res.setEncoding([encoding]):设置默认的编码,当data事件被触发时,数据将会以encoding编码。
    • res.pause():暂停接收数据和发送事件,方便实现下载功能。
    • res.resume():从暂停的状态中恢复

看下下面这个例子,HTTP客户端向服务器发起Get请求。

var http = require('http');
var options = {
  host: "127.0.0.1",
  port: 3000,
  path: "/index.html?name=lupeng"
}
var req = http.get(options,function(res){
  res.setEncoding('utf8');
  var content = '';
  res.on('data',function(data){
    console.log(data);
  });
});