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

node开发指南的更多相关文章

  1. Node.js开发指南中的例子(mysql版)

    工作原因需要用到nodejs,于是找到了<node.js开发指南>这本书来看看,作者BYVoid 为清华大学计算机系的高材生,年纪竟比我还小一两岁,中华地广物博真是人才辈出,佩服. 言归正 ...

  2. 学习Nodejs:《Node.js开发指南》微博项目express2迁移至express4过程中填的坑

    <Node.js开发指南>项目地址https://github.com/BYVoid/microblog好不容易找到的基础版教程,但书中是基于express2的,而现在用的是express ...

  3. 《node.js开发指南》partial is not defined的解决方案

    由于ejs的升级,<node.js开发指南>中使用的 partial 函数已经摒弃,使用foreach,include代替 原来的代码是: <%- partial('listitem ...

  4. nodejs开发指南读后感

    nodejs开发指南读后感 阅读目录 使用nodejs创建http服务器; supervisor的使用及nodejs常见的调式代码命令了解; 了解Node核心模块; ejs模板引擎 Express 理 ...

  5. AngularJS开发指南16:AngularJS构建大型Web应用详解

    AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML功能,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...

  6. Spark开发指南

    原文链接http://www.sxt.cn/info-2730-u-756.html 目录 Spark开发指南 简介 接入Spark Java 初始化Spark Java 弹性分布式数据集 并行集合 ...

  7. [翻译]现代java开发指南 第二部分

    现代java开发指南 第二部分 第二部分:部署.监控 & 管理,性能分析和基准测试 第一部分,第二部分 =================== 欢迎来到现代 Java 开发指南第二部分.在第一 ...

  8. [翻译]现代java开发指南 第一部分

    现代java开发指南 第一部分 第一部分:Java已不是你父亲那一代的样子 第一部分,第二部分 =================== 与历史上任何其他的语言相比,这里要排除c语言和cobol语言,现 ...

  9. nodejs 开发指南 书中小项目 代码

    最近 在学习node.js 先看了下语法 ,然后就看这个开发指南感觉书还是很有用,但是代码太旧了,网上也没有最新的,所以就自己查着前人的痕迹和自己修改,现在可以跑了. https://github.c ...

随机推荐

  1. 后缀数组:倍增法和DC3的简单理解

    一些定义:设字符串S的长度为n,S[0~n-1]. 子串:设0<=i<=j<=n-1,那么由S的第i到第j个字符组成的串为它的子串S[i,j]. 后缀:设0<=i<=n- ...

  2. 【转载】DOS 系统和 Windows 系统有什么关系?为什么windows系统下可以执行dos命令?

    作者:bombless 因为不同的系统都叫 Windows ,这些系统在界面上也有一定连续性并且因此可能造成误解,所以有必要稍微梳理一下几个不同的 Windows 系统.首先是 DOS 上的一个图形界 ...

  3. [转]NandFlash和NorFlash的区别

    一. NAND和NOR的比较 NOR和NAND是现在市场上两种主要的非易失闪存技术.Intel于1988年首先开发出NOR flash技术,彻底改变了原先由EPROM 和EEPROM一统天下的局面.紧 ...

  4. Query Designer:Condition,根据KeyFigure值来过滤数据

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  5. oracle更改用户名

    例如,用户名test1改为test2,在plsql界面中不支持直接更改,只能通过sql更改 1.查询系统user$中的user#值 select user#,name from user$ where ...

  6. C++备忘录

    参考资料: 1. <C++编程思想(第一卷)> 知识点: ● register变量:它是一种局部变量类型.它告诉编译器尽快访问该变量.一般会把变量放在寄存器中,但不保证一定会.不能得到或计 ...

  7. an interview question(2)

    感觉现在好多面试题还是很注重基础的,今天面试时就遇到这题,回来一查后才知道此题是国内某著名通信公司的一道机试题:) 给定一个数组input[ ],如果数组长度n为奇数,则将数组中最大的元素放到 out ...

  8. Android Intent

    Intent在Android中的重要性不言而喻.本文主要总结下Intent使用过程中需要注意的一些问题. 1.隐式Intent AndroidManifest.xml声明时<intent-fil ...

  9. [转]Android开源项目第二篇——工具库篇

    本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多 ...

  10. plist基本操作

    重要概念:某些路径下“只能读,不能写”的原因 iPhone.ipad真机上 Resouces文件夹:是只读的,无法写入. document 和temp文件夹:可读,可写. 一.工程结构