Node.js 能做什么
正如 JavaScript 为客户端而生,Node.js 为网络而生。Node.js 能做的远不止开发一个网站那么简单,使用 Node.js,你可以轻松地开发:
- 具有复杂逻辑的网站;
- 基于社交网络的大规模 Web 应用;
- Web Socket 服务器;
- TCP/UDP 套接字应用程序;
- 命令行工具;
- 交互式终端程序;
- 带有图形用户界面的本地应用程序;
- 单元测试工具;
- 客户端 JavaScript 编译器。
Node.js 内建了 HTTP 服务器支持,也就是说你可以轻而易举地实现一个网站和服务器的组合。这和 PHP、Perl 不一样,因为在使用 PHP 的时候,必须先搭建一个 Apache 之类的 HTTP 服务器,然后通过 HTTP 服务器的模块加载或 CGI 调用,才能将 PHP 脚本的执行结果呈现给用户。而当你使用 Node.js 时,不用额外搭建一个 HTTP 服务器,因为 Node.js 本身就内建了一个。这个服务器不仅可以用来调试代码,而且它本身就可以部署到产品环境,它的性能足以满足要求。
Node.js 还可以部署到非网络应用的环境下,比如一个命令行工具。Node.js 还可以调用 C/C++ 的代码,这样可以充分利用已有的诸多函数库,也可以将对性能要求非常高的部分用 C/C++ 来实现。
创建一个 HTTP 服务器
//app.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.");
EventEmitter 的用法:
//event.js
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
console.log('some_event occured.');
});
setTimeout(function() {
event.emit('some_event');
}, 1000);
运行这段代码,1秒后控制台输出了 some_event occured.。其原理是 event 对象注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在1000毫秒以后向 event 对象发送事件 some_event,此时会调用 some_event 的监听器。
Node.js调试工具
node-inspector
util.inherits 的用法,示例如下:
var util = require('util');
function Base() {
this.name = 'base';
this.base = 1991;
this.sayHello = function() {
console.log('Hello ' + this.name);
};
}
Base.prototype.showName = function() {
console.log(this.name);
};
function Sub() {
this.name = 'sub';
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
//objSub.sayHello();
console.log(objSub);
我们定义了一个基础对象 Base 和一个继承自 Base 的 Sub,Base 有三个在构造函数内定义的属性和一个原型中定义的函数,通过 util.inherits 实现继承。运行结果如下:
base
Hello base
{ name: 'base', base: 1991, sayHello: [Function] }
sub
{ name: 'sub' }
注意,Sub 仅仅继承了 Base 在原型中定义的函数,而构造函数内部创造的 base 属性和 sayHello 函数都没有被 Sub 继承。同时,在原型中定义的属性不会被 console.log 作为对象的属性输出。如果我们去掉 objSub.sayHello(); 这行的注释,将会看到:
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^ TypeError: Object #<Sub> has no method 'sayHello'
at Object.<anonymous> (/home/byvoid/utilinherits.js:29:8)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)
fs 模块函数表
打开文件
fs.open(path,flags, [mode], [callback(err, fd)])
fs.openSync(path, flags, [mode])
**关闭文件 **
fs.close(fd, [callback(err)])
fs.closeSync(fd)
读取文件 (文件描述符)
fs.read(fd,buffer,offset,length,position, [callback(err, bytesRead, buffer)])
fs.readSync(fd, buffer, offset, length, position)
写入文件 (文件描述符)
fs.write(fd,buffer,offset,length,position, [callback(err, bytesWritten, buffer)])
fs.writeSync(fd, buffer, offset, length, position)
**读取文件内容 **
fs.readFile(filename,[encoding],[callback(err, data)])
fs.readFileSync(filename, [encoding])
**写入文件内容 **
fs.writeFile(filename, data,[encoding], [callback(err)])
fs.writeFileSync(filename, data, [encoding])
删除文件
fs.unlink(path, [callback(err)])
fs.unlinkSync(path)
**创建目录 **
fs.mkdir(path, [mode], [callback(err)])
fs.mkdirSync(path, [mode])
删除目录
fs.rmdir(path, [callback(err)])
fs.rmdirSync(path)
**读取目录 **
fs.readdir(path, [callback(err, files)])
fs.readdirSync(path)
**获取真实路径 **
fs.realpath(path, [callback(err, resolvedPath)])
fs.realpathSync(path)
**更名 **
fs.rename(path1, path2, [callback(err)])
fs.renameSync(path1, path2)
**截断 **
fs.truncate(fd, len, [callback(err)])
fs.truncateSync(fd, len)
**更改所有权 **
fs.chown(path, uid, gid, [callback(err)])
fs.chownSync(path, uid, gid)
**更改所有权 (文件描述符) **
fs.fchown(fd, uid, gid, [callback(err)])
fs.fchownSync(fd, uid, gid)
更改所有权 (不解析符号链接)
fs.lchown(path, uid, gid, [callback(err)])
fs.lchownSync(path, uid, gid)
**更改权限 **
fs.chmod(path, mode, [callback(err)])
fs.chmodSync(path, mode)
更改权限 (文件描述符)
fs.fchmod(fd, mode, [callback(err)])
fs.fchmodSync(fd, mode)
更改权限 (不解析符号链接)
fs.lchmod(path, mode, [callback(err)])
fs.lchmodSync(path, mode)
获取文件信息
fs.stat(path, [callback(err, stats)])
fs.statSync(path)
**获取文件信息 (文件描述符) **
fs.fstat(fd, [callback(err, stats)])
fs.fstatSync(fd)
获取文件信息 (不解析符号链接)
fs.lstat(path, [callback(err, stats)])
fs.lstatSync(path)
**创建硬链接 **
fs.link(srcpath, dstpath, [callback(err)])
fs.linkSync(srcpath, dstpath)
**创建符号链接 **
fs.symlink(linkdata, path, [type], [callback(err)])
fs.symlinkSync(linkdata, path, [type])
读取链接
fs.readlink(path, [callback(err, linkString)])
fs.readlinkSync(path)
修改文件时间戳
fs.utimes(path, atime, mtime, [callback (err)])
fs.utimesSync(path, atime, mtime)
修改文件时间戳(文件描述符)
fs.futimes(fd, atime, mtime, [callback (err)])
fs.futimesSync(fd, atime, mtime)
**同步磁盘缓存 **
fs.fsync(fd, [callback(err)])
fs.fsyncSync(fd)
获取 GET 请求内容
//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);
在浏览器中访问 http://127.0.0.1:3000/username=byvoid&email=byvoid@byvoid.com,我们可以看到浏览器返回的结果:
{ search: '?name=byvoid&email=byvoid@byvoid.com',
query: { name: 'byvoid', email: 'byvoid@byvoid.com' },
pathname: '/user',
path: '/user?name=byvoid&email=byvoid@byvoid.com',
href: '/user?name=byvoid&email=byvoid@byvoid.com' }
通过 url.parse原始的 path 被解析为一个对象,其中 query 就是我们所谓的 GET 请求的内容,而路径则是 pathname。
获取 POST 请求内容
//httpserverrequestpost.js
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res) {
var post = '';
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
上面代码并没有在请求响应函数中向客户端返回信息,而是定义了一个 post 变量,用于在闭包中暂存请求体的信息。 通过 req 的 data 事件监听函数, 每当接受到请求体的数据,就累加到 post 变量中。在 end 事件触发后,通过 querystring.parse 将 post 解析为真正的 POST 请求格式,然后向客户端返回。
使用 Node.js进行 Web 开发
1.安装 Express
npm install -g express
2.建立工程
express -t ejs microblog
cd microblog && npm install