1.核心模块
核心模块是Node.js的心脏,由一些精简高效的库组成,为其提供了基本的API。
2.全局对象
global。所有的的全局变量都是其属性。其根本的作用是作为全局变量的宿主。
3.全局变量
1.process:描述当前Node.js的进程状态的对象,提供一个与操作系统的简单接口。
方法 process.argv 命令行参数数组 三个参数1.node 2.脚本文件名 3.运行参数
1.process.stdout: 标准输出流,通常使用的console.log()向标准输出打印字符,而process.stdout.write提供了更底层的接口。
2.process.stdin:标准输入流 初始状态为暂停 要想从标准输入读取数据,必须恢复流,并手动
编写流的事件相应函数。
process.stdin.resume(); //回复流
process.stdin.on('data', function(data) {//监听事件相应
process.stdout.write('read from console: ' + data.toString());//返回输入内容
});
在终端输入 Andy
在终端输出 read from console:Andy
如果不退出CTRL+C 事件将一直处于相应状态
3.process.nextTick(callback):为事件循环设置一项任务,Node.js会在下次事件循环响应时调
用callback;
PS:因为NODE.JS进程只有一个线程,因此在任何时刻都只有一个事件在执行,如果这个事件
占用大量CPU时间,执行事件循环中的下一个事件就需要等待很久,因此NODE.JS的一个原则
是尽量缩短每个事件的执行时间。process.nextTick提供了一个这样的工具,可以把复杂的
工作拆散,变成一个个较小的事件。
function a(args, callback) {
b(args);
callback();
}
a(function c() {
d();
});
假设a,b是两个耗时的程序。
执行流程:1.执行a,把c当作参数传给args
2.执行b,这里的参数为函数c
3.执行c
4.执行d
5.执行回调
用process.nextTick改写
function doSomething(args, callback) {
somethingComplicated(args);
process.nextTick(callback);
}
doSomething(function onEnd() {
compute();
});
改写后的程序会把上面耗时的操作拆分为两个事件,减少每个事件的执行时间,提高事件相应速度。不要使用setTimeout(fn,0)代替,因为这个效率要低的多。
4.其他看API文档
2.console:用于向标准输出流或者标准错误流输出字符
1.console.log() 向标准输出流打印字符并以换行符
2.console.error() 向标准错误流输出字符并以换行符
3.console.trace() 向标准错误流输出当前的调用栈
4.常用工具
1.util:核心模块,提供常用的函数集合。
1.util.inherits(constructor,superConstructor)是一个实现对象间原型继承的函数。子类继
承超类。JS中没有提供对象继承的语言级别特性,而是通过原型复制来实现的。
var util = require('util'); //请求模块
function Base() { //Base构造函数
this.name = 'base';
this.base = 1991;
this.sayHello = function() {
console.log('Hello ' + this.name);
};
}
Base.prototype.showName = function() {//原型方法showName
console.log(this.name);
};
function Sub() { //Sub构造函数
this.name = 'sub';
}
util.inherits(Sub, Base); //Sub继承Base的原型
var objBase = new Base(); //实例化
objBase.showName(); //base
objBase.sayHello(); //Hello base
console.log(objBase); //Base{name:'base',base:1991,sayHello:[function]}
//原型属性不会被console.log()作为对象的属性输出
var objSub = new Sub();
objSub.showName(); //Sub
objSub.sayHello(); //报错 因为Sub只是继承Base的原型,sayHello不在原型
console.log(objSub); Sub{name:'sub'}
2.util.inspect(object,[showhidden],[depth],[colors])是一个将任意对象转换为字符串的方法,
通常用于调试和错误输出。
参数:唯一的必选参数 object :要转换的对象
showhidden 默认为false 如果为true 将会输出更多信息
depth 表示递归的最大层数 默认为2层 null为无限制
colors 如果值为true 输出格式将会以ANSI颜色编码,更漂亮
3.其他查API文档
5.事件驱动events:最重要的模块,没有之一,是NODE.JS编程的基石。不仅用于用户代码与node.js下
层事件循环的交互,还几乎被所有的模块依赖。
1.events模块只提供一个对象:events.EventEmitter
1.events.EventEmitter:事件发射与事件监听器功能的封装。
events.EventEmitter的每个事件由一个事件名和若干参数组成。对于每个事件,支持若干
个事件监听器。当事件发射时,注册到这个事件的事件监听器被依次调用,事件参数作为
回调函数参数传递。
var events = require('events'); //请求模块
var emitter = new events.EventEmitter(); //实例化对象
emitter.on('someEvent', function(arg1, arg2) { //监听someEvent
console.log('listener1', arg1, arg2); //执行回调
});
emitter.on('someEvent', function(arg1, arg2) { //监听someEvent
console.log('listener2', arg1, arg2); //执行回调
});
emitter.emit('someEvent', 'byvoid', 1991); //触发事件
events.EventEmitter常用API
1.EventEmitter.on(event,callback);
为指定事件注册一个监听器,接受一个字符串(事件名) 和一个回调函数
2.EventEmitter.emit(event,[arg1],[arg2],[arg3]……);触发事件event,
并传入若干参数到事件监听器的参数表
3.EventEmitter.once(event,callback) 与on不同的是最多触发一次,触发后
立即解除该监听器。
4.EventEmitter.removeListener(event,Listener)移除指定事件的某个监听
器,Listener必须是该事件已经注册过的监听器。
5.EventEmitter.removeALLListener([event]);移除所有事件的所有监听器,
如果指定event,则移除指定事件的所有监听器。
6.error 当error被发射时,EventEmitter规定如果没有响应的监听器,NODE.JS会把它当作异常,退出程序并打印调用栈。我们一般要为会发射error时间的对象设置监听器。避免遇到错误后整个程序崩溃。
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
PS:大多时候不会直接使用EventEmitter,而生在对象中继承它,包括FS, .NET, HTTP,
只要支持事件相应的模块的核心模块都是EventEmitter的子类。
原因1:具有某个实体功能的对象实现事件符合语义,事件的监听和发射应该是一个对象的方法。
2:JS是基于原因支持部分多重继承,继承EventEmitter不会打乱对象原有的继承关系。
2.文件系统FS
FS模块是文件操作的封装,它提供了文件的读取、写入、更名、删除、遍历目录、连接等POSIX
文件系统操作。FS所有的操作都提供的同步和异步两个版本。
1.fs.readFile(fileName,[encoding],[callback(err,data)]).
唯一的一个必选参数 fileName 要读取的文件名
encoding 文件的字符编码
callback 回调函数
两个参数1.err 表示有没有错误发射
2.data 文件内容 如果指定encoding,data为解析后的字符串,否则将会以
buffer形式表示的二进制数据。
var fs = require('fs');
fs.readFile('content.txt', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
//二进制形式输出
var fs = require('fs');
fs.readFile('content.txt', 'utf-8', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
//UTF编码形式输出
NODE.JS通常有且只有一个回调函数。回调函数中第一个参数实际上是error,其余的参数
是其他返回的内容,如果没有错误发生error值为null或者undefined。如果有错误,error通常是error对象的实例。
2.同步:fsreadFileSync(fileName,[callback(err,filedata)])
3.fs.open(path,flags,[mode],[callback(err,filedata)])是POSIX open函数的封装。
必选两个参数 path为文件的路径
flags可以是以下值
r 只读
r+ 读写
w 只写,不存在则创建。
w+ 读写,不存在则创建。
a 追加模式打开,不存在则创建。
a+ 以读取追加模式打开,不存在则创建。
mode用于创建文件时给文件指定权限 默认 0666
4.fs.read(fd,buffer,offset,length,position,[callback[err,bytesRead,buffer]])
是POSIX read函数的封装.实现从指定的文件描述符fd 中读取数据并写入buffer指向的缓冲区
对象。offset为buffer给入的偏移量。length是要从文件中读取的字节数。position是文件读取的起始位置,如果为null,则从当前文件指针的位置读取。回调函数传递的bytesRead,buffer分表表示读取的字节数和缓冲区对象。
var fs = require('fs');
fs.open('content.txt', 'r', function(err, fd) {//以只读方式打开文件
if (err) {
console.error(err);
return;
}
var buf = new Buffer(8);
fs.read(fd, buf, 0, 8, null, function(err, bytesRead, buffer) {
if (err) {
console.error(err);
return;
}
console.log('bytesRead: ' + bytesRead);
console.log(buffer);
})
});
一般来说,没有必要采取这样的方法,很麻烦。
5.其他API看文档。
6.http服务器
1.http.Server是http模块中http服务器对象,用node.js所有基于http协议的系统。提供仅仅是流控制和简单的消息解析,所有高层功能都要通过它的接口来实现,
//httpserver.js
var http = require('http'); //
http.createServer(function(req, res) { //创建服务器
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');//响应体
res.end('<p>Hello World</p>');//结束并发送
}).listen(3000);//监听端口号
console.log("HTTP server is listening at port 3000.");
1.request,当客户端请求到来时,触发该事件。提供两个参数 req,res,
分别是http.ServerRequest和http.ServerResponse的实例,表示请求和响应信息。
2.connection: 当TCP连接简历时,该事件被触发,提供一个参数socket,为net.socket的实例
。connection的粒度要大于request,因为客户端在Keep-Alive的模式下可能会在同一个连接内
多次请求。
3.close:当服务器关闭时,该事件被触发。注意不是在用户连接断开时。
4.其他 checkContinue、upgrade、clientError等等
最常用的request,http创建了一个捷径。http.createServer([requestListener]),创建一个
http服务器并将requestListener作为request事件的监听函数。
上面的代码实际是
//httpserver.js
var http = require('http');
var server = new http.Server();
server.on('request', function(req, res) {//注册请求事件
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello World</p>');
});
server.listen(3000);
console.log("HTTP server is listening at port 3000.");
2.http.ServerRequest:HTTP请求的信息。由http.Server的request事件发送,作为第一个参数传递
,http请求一般可以分为两部分:请求头(RequestHeader)和请求体(RequestBody).
由三个事件用于控制请求体传输:
1.data:当请求体数据带来时,触发事件。该事件提供一个参数chunk,表示接受的数据,
如果该事件没有被监听,那么请求体将会被抛弃,该事件可以被调用多次。
2.end:当请求体数据传输完成时,该事件被触发,以后将不会再有数据到来
3.close:用户当前请求结束时,触发事件,不同于end,如果用户强制终止了传输,也会调用close。
4.其他属性看API文档
3.获取GET请求内容
由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括?后面的部分,因此可以手动解析后面的内容作为GET请求的参数。 URL模块中parse函数提供这个功能。
//httpserverrequestget.js
var http = require('http'); //请求需要的模块
var url = require('url');
var util = require('util');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(util.inspect(url.parse(req.url, true))); //!!
}).listen(3000); //在localhost:3000输入路径
以localhost:3000/uesr?name=Andy&email=445864742@qq.com为例:
返回:{
search:'?name=Andy&email=445864742@qq.com',
query:{name:'Andy',email:'445864742@qq.com'}, //GET请求的内容
pathname:'/user',
path:'/uesr?name=Andy&email=445864742@qq.com',
href:'/uesr?name=Andy&email=445864742@qq.com'
}
4.获取POST内容
POST请求的内容全部都在请求体中。
//httpserverrequestpost.js
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res) {
var post = ''; //定义一个post用于暂存请求体内容
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
通过req的data事件监听函数,每当接收到请求体的数据,就累加到post中。在end触发以后,
通过querystring.parse将post解析为真正的post数据,然后向客户端返回。(实际项目中不能
这么用,因为由严重的效率和安全问题);
5.http.ServerResponse:返回给客户端的信息,决定了用户最终能看到的结果。它也是由
http.Server的request事件发送的,作为第二个参数传递,简称为response或者res.
三个参数
1.response.writeHead(statusCode,[headers]):向请求的客户端发送响应头。
statusCode是HTTP状态码
200:请求成功
404:未找到
等等
headers:一个类似关联数组的对象,表示响应头的每个属性。该函数在一个请求内最多能使用一次,如果不调用则自动生成一个响应头。
2.response.write(data,[encoing]):向请求的客户端发送响应内容。
data是一个buffer或字符串,表示要发送的内容。
如果data是字符串,那么就需要指定encoding来表明编码方式,默认为UTF-8
在调用response.end之前,可以多次调用response.write
3.response.end([data],[encoding]):结束响应,告知客户端所有发送都已经完成。当
所有要返回的内容发送完毕的时候,该函数 必须 被调用一次。两个可选参数如果要写的
话用法同data
6.HTTP客户端
http模块提供了两个函数http.request和http.get,功能是作为客户端向HTTP服务器发起请求
http.request(options,callback)发起http请求。
options :一个类似关联数组的对象,表示请求的参数
常用参数
host:请求网站的域名或者IP地址
port:请求的端口,默认为80
method:请求方法,默认为GET
path:请求的相对于根的路径,默认是/。
headers:一个类似关联数组的对象,请求的头内容
callback:请求的回调函数
传递一个参数,为http.ClientRespongse的实例
http.request返回一个http.ClientRespongse的实例。
//httprequest.js
var http = require('http');
var querystring = require('querystring');
var contents = querystring.stringify({ //将对象转换成字符串
name: 'byvoid',
email: 'byvoid@byvoid.com',
address: 'Zijing 2#, Tsinghua University',
});
var options = {
host: 'www.byvoid.com',
path: '/application/node/post.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length' : contents.length
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});
req.write(contents);
req.end(); //这个必须有
1.http.get(options,callback) http.request的简化版,区别在于http.get自动
将请求方法设为了GET请求,也不需要设置req.end();
1.http.ClientRequest是由http.request和http.get返回产生的对象,表示一个已经产生
而且正在进行http请求。提供一个response事件,即http.get或者http.request,第二个参数时指定的回调函数的绑定对象,我们可以显式地绑定这个事件的监听函数。
//httpresponse.js
var http = require('http');
var req = http.get({host: 'www.byvoid.com'});
req.on('response', function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});
http.ClientRequest提供了write和end函数,用于向服务器发送请求体,通常用于post,和
put等操作。结束之后必须用end
request.abort():终止发送的请求
request.setTimeout([callback],timeout)
还有其他参数看API
2.http.ClientResponse
提供三个事件 data 数据到达时触发 一个参数chunk表示接收到的数据
end 传输结束时触发
close连接结束时触发
http.ClientResponsed的一些属性用于表示请求的结果状态
statusCode 200、404、500等
httpVersion 协议版本
headers HTTP请求头
trailers 请求尾
http.ClientResponsed的的特殊函数
response.setEncoding
response.pause 暂停接收数据和发送事件,方便下载
response.resume 从暂停状态中恢复