Node.js入手笔记材料

来源:互联网 发布:上古卷轴5mod捏脸数据 编辑:程序博客网 时间:2024/04/28 01:31

Node.js入手笔记材料

简单的说 Node.js 就是运行在服务端的JavaScript。

Node.js 是一个基于ChromeJavaScript 运行是建立的一个平台,是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

1    安装

Node.js安装包及源码下载地址为:https://nodejs.org/en/download/

查看版本:

#node -v

创建第一个Node.js程序,编辑hello.js,内容如下:

console.log("helloworld");

然后node hello.js进行执行。

               在Ubuntu中安装命令:

sudoapt-get install nodejs

sudoapt-get install npm

 

2    Node.js应用

 

使用PHP来编写后端的代码时,需要Apache或者 Nginx 的HTTP 服务器,并配上 mod_php5 模块和php-cgi。

从这个角度看,整个"接收 HTTP 请求并提供 Web 页面"的需求根本不需要 PHP 来处理。

不过对 Node.js 来说,概念完全不一样了。使用 Node.js 时,我们不仅仅在实现一个应用,同时还实现了整个 HTTP 服务器。事实上,我们的 Web 应用以及对应的 Web 服务器基本上是一样的。

 

 

 

 Node.js 应用由几部分组成的:

3       引入 required 模块

4       创建服务器

5       接收请求与响应请求 

 

6    创建 Node.js 应用

varhttp = require('http');

http.createServer(function(request, response) {

    // 发送 HTTP头部

    // HTTP 状态值: 200 : OK

    // 内容类型: text/plain

    response.writeHead(200, {'Content-Type':'text/plain'});

    // 发送响应数据 "Hello World"

    response.end('Hello World\n');

}).listen(8888);

// 终端打印如下信息

console.log('Serverrunning at http://127.0.0.1:8888/');

 

使用http.createServer() 方法创建服务器,并使用 listen 方法绑定 8888 端口。函数通过 request, response 参数来接收和响应数据。

第一行请求(require)Node.js 自带的 http 模块,并且把它赋值给http 变量。

调用 http 模块提供的函数:createServer 。这个函数会返回一个对象,这个对象有一个叫做 listen 的方法,这个方法有一个数值参数,指定这个 HTTP 服务器监听的端口号。

 

 

7    NPM

NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,例如:

l   允许用户从NPM服务器下载别人编写的第三方包到本地使用。

l   允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。

l   允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

 "npm-v" 来测试是否成功安装。

7.1    安装

npm 安装 Node.js 模块语法格式如下:

$ npm install <Module Name>

 npm 命令安装常用的 Node.js web框架模块 express:

#npm install express

npm 的包安装分为本地安装(local)、全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已。

7.2    本地安装

1. 将安装包放在./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。

2. 可以通过require() 来引入本地安装的包。

7.3    全局安装

1. 将安装包放在/usr/local 下或者你 node 的安装目录(例如mac是在lib/node_modules中)。

2. 可以直接在命令行里使用。

查看安装信息

你可以使用以下命令来查看所有全局安装的模块:

$ npm list -g

如果要查看某个模块的版本号,可以使用命令如下:

$ npm list <module_name>

7.4    使用 package.json

package.json 位于模块的目录下,用于定义包的属性。接下来让我们来看下 express 包的 package.json 文件,位于 node_modules/express/package.json

Package.json 属性说明

name - 包名。

version - 包的版本号。

description - 包的描述。

homepage - 包的官网 url 。

author - 包的作者姓名。

contributors - 包的其他贡献者姓名。

dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。

repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。

main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。

keywords - 关键字

 

7.5    卸载模块

我们可以使用以下命令来卸载 Node.js 模块。

#npm uninstall express

卸载后,可以到 /node_modules/ 目录下查看包是否还存在,或者使用以下命令查看:

#npm ls

7.6    更新模块

可以使用以下命令更新模块:

$ npm update express

7.7    搜索模块

使用以下来搜索模块:

$ npm search express

7.8    创建模块

创建模块,package.json 文件是必不可少的。我们可以使用 NPM 生成 package.json 文件,生成的文件包含了基本的结果。

#npm init

用以下命令来发布模块:

#npm publish

如果你以上的步骤都操作正确,你就可以跟其他模块一样使用 npm 来安装。

 

8    Node.js REPL(交互式解释器)

 

Node.jsREPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Window 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应。

Node 自带了交互式解释器,可以执行以下任务:

l   读取 - 读取用户输入,解析输入了Javascript数据结构并存储在内存中。

l   执行 - 执行输入的数据结构

l   打印 - 输出结果

l   循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。

REPL 命令

ctrl + c - 退出当前终端。

ctrl + c 按下两次 - 退出 Node REPL。

ctrl + d - 退出 Node REPL.

向上/向下键 - 查看输入的历史命令

tab 键 - 列出当前命令

.help - 列出使用命令

.break - 退出多行表达式

.clear - 退出多行表达式

.save filename - 保存当前的 NodeREPL 会话到指定文件

.load filename - 载入当前 NodeREPL 会话的文件内容。

 

 

9    Node.js 回调函数

Node.js 异步编程的直接体现就是回调。

异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。

我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。

9.1    阻塞代码

 

 

输入input.txt内容如下:

baidu  www.baidu.com

代码如下:

varfs=require("fs");

vardata=fs.readFileSync('input.txt');

console.log(data.toString());

console.log("completed");

9.2    异步代码

如下:

var fs= require("fs");

 

fs.readFile('input.txt',function (err, data) {

    if (err) return console.error(err);

    console.log(data.toString());

});

 

console.log("程序执行结束!");

 fs.readFile()是异步函数用于读取文件。如果在读取文件过程中发生错误,错误 err 对象就会输出错误信息。

如果没发生错误,readFile 跳过 err 对象的输出,文件内容就通过回调函数输出。

10         Node.js 事件循环

Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。

Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。

Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。

Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

10.1 事件驱动程序

Node.js 使用事件驱动模型,当webserver接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。

这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者事件驱动IO)

在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件。

               过程代码如下:

// 引入 events模块

varevents = require('events');

// 创建 eventEmitter对象

vareventEmitter = new events.EventEmitter();

// 绑定事件及事件的处理程序

eventEmitter.on('eventName',eventHandler);

// 触发事件

eventEmitter.emit('eventName');

               实例如下:

// 引入 events模块

varevents = require('events');

// 创建 eventEmitter对象

vareventEmitter = new events.EventEmitter();

 

// 创建事件处理程序

varconnectHandler = function connected() {

   console.log('连接成功。');

 

   // 触发data_received事件

   eventEmitter.emit('data_received');

}

 

// 绑定 connection事件处理程序

eventEmitter.on('connection',connectHandler);

 

// 使用匿名函数绑定 data_received事件

eventEmitter.on('data_received',function(){

   console.log('数据接收成功。');

});

// 触发 connection事件

eventEmitter.emit('connection');

console.log("程序执行完毕。");

 

 

11          Node.js EventEmitter

Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件,一个fs.readStream对象会在文件被打开的时候发出一个事件。所有这些产生事件的对象都是 events.EventEmitter 的实例。

events 模块只提供了一个对象:events.EventEmitter。EventEmitter 的核心就是事件触发与事件监听器功能的封装。

代码示例:

varEventEmitter = require('events').EventEmitter;

varevent = new EventEmitter();

event.on('some_event',function() {

    console.log('some_event事件触发');

});

setTimeout(function(){

    event.emit('some_event');

}, 1000);

1 秒后控制台输出了 'some_event事件触发'。其原理是 event 对象注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在 1000 毫秒以后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。

EventEmitter 的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持若干个事件监听器。

当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。

EventEmitter 提供了多个属性,如 on 和 emit。on 函数用于绑定事件函数,emit 属性用于触发一个事件。

11.1 方法

序号

方法 & 描述

1

addListener(event, listener)
指定事件添加一个听器到听器数组的尾部。

2

on(event, listener)
指定事件注一个听器,接受一个字符串 event 和一个回

server.on('connection', function (stream) {   console.log('someone connected!'); });

3

once(event, listener)
指定事件注一个听器,即听器最多只会触发一次,触发后立刻解除该监听器。

server.once('connection', function (stream) {   console.log('Ah, we have our first user!'); });

4

removeListener(event, listener)

移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。

它接受两个参数,第一个是事件名称,第二个是回调函数名称。

var callback = function(stream) {   console.log('someone connected!'); }; server.on('connection', callback); // ... server.removeListener('connection', callback);

5

removeAllListeners([event])
移除所有事件的所有听器,如果指定事件,移除指定事件的所有听器。

6

setMaxListeners(n)
情况下, EventEmitters如果你添加的听器超 10个就会输出警告信息。 setMaxListeners用于提高听器的默限制的量。

7

listeners(event)
返回指定事件的听器数组

8

emit(event, [arg1], [arg2], [...])
按参行每个听器,如果事件有注册监听返回 true,否返回 false

11.2       类方法

序号

方法 & 描述

1

listenerCount(emitter, event)
返回指定事件的听器量。

11.3       事件

序号

事件 & 描述

1

newListener

·       event -字符串,事件名称

·       listener -处理事件函数

该事件在添加新监听器时被触发。

2

removeListener

·       event -字符串,事件名称

·       listener -处理事件函数

从指定监听器数组中删除一个监听器。需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。

11.4 示例

varevents = require('events');

vareventEmitter = new events.EventEmitter();

 

// 监听器 #1

varlistener1 = function listener1() {

   console.log('监听器 listener1执行。');

}

 

// 监听器 #2

varlistener2 = function listener2() {

  console.log('监听器 listener2执行。');

}

 

// 绑定 connection事件,处理函数为 listener1

eventEmitter.addListener('connection',listener1);

 

// 绑定 connection事件,处理函数为 listener2

eventEmitter.on('connection',listener2);

 

vareventListeners =require('events').EventEmitter.listenerCount(eventEmitter,'connection');

console.log(eventListeners+ "个监听器监听连接事件。");

 

// 处理 connection事件

eventEmitter.emit('connection');

 

// 移除监绑定的 listener1函数

eventEmitter.removeListener('connection',listener1);

console.log("listener1不再受监听。");

 

// 触发连接事件

eventEmitter.emit('connection');

 

eventListeners= require('events').EventEmitter.listenerCount(eventEmitter,'connection');

console.log(eventListeners+ "个监听器监听连接事件。");

 

console.log("程序执行完毕。");

 

EventEmitter 定义了一个特殊的事件error,它包含了错误的语义,在遇到异常的时候通常会触发 error 事件。

当 error 被触发时,EventEmitter规定如果没有响 应的监听器,Node.js会把它当作异常,退出程序并输出错误信息。

我们一般要为会触发 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。

11.5 继承EventEmitter

大多数时候我们不会直接使用EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。

原因有两点:

首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发射应该是一个对象的方法。

其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承EventEmitter 不会打乱对象原有的继承关系。

 

12         Node.js Buffer(缓冲区)

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

               示例:

buf =new Buffer(256);

len =buf.write("www.runoob.com");

console.log("写入字节数 : "+  len);

读出:

buf =new Buffer(26);

for(var i = 0 ; i < 26 ; i++) {

  buf[i] = i + 97;

}

 

console.log(buf.toString('ascii'));       //输出: abcdefghijklmnopqrstuvwxyz

console.log(buf.toString('ascii',0,5));   //输出: abcde

console.log(buf.toString('utf8',0,5));    //输出: abcde

console.log( buf.toString(undefined,0,5)); //使用 'utf8'编码,并输出: abcde

将 Node Buffer 转换为 JSON 对象的函数语法格式如下:

buf.toJSON()

Node 缓冲区合并的语法如下所示:

Buffer.concat(list[, totalLength])

Node Buffer 比较的函数语法如下所示, 该方法在 Node.jsv0.12.2 版本引入:

buf.compare(otherBuffer);

Node 缓冲区拷贝语法如下所示:

buf.copy(targetBuffer[, targetStart[,sourceStart[, sourceEnd]]])

Node 缓冲区裁剪语法如下所示:

buf.slice([start[, end]])

Node 缓冲区长度计算语法如下所示:

buf.length;

 

13          Node.js Stream(流)

Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。例如,对http 服务器发起请求的request 对象就是一个 Stream,还有stdout(标准输出)。

Node.js,Stream 有四种流类型:

l   Readable - 可读操作。

l   Writable - 可写操作。

l   Duplex - 可读可写操作.

l   Transform - 操作被写入数据,然后读出结果。

所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

l   data - 当有数据可读时触发。

l   end - 没有更多的数据可读时触发。

l   error - 在接收和写入过程中发生错误时触发。

l   finish - 所有数据已被写入到底层系统时触发。

示例:

var fs= require("fs");

vardata = '';

// 创建可读流

varreaderStream = fs.createReadStream('input.txt');

// 设置编码为 utf8

readerStream.setEncoding('UTF8');

// 处理流事件 --> data, end, and error

readerStream.on('data',function(chunk) {

   data += chunk;

});

readerStream.on('end',function(){

   console.log(data);

});

readerStream.on('error',function(err){

   console.log(err.stack);

});

console.log("程序执行完毕");

 

管道流,管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。

var fs= require("fs");

 

// 创建一个可读流

varreaderStream = fs.createReadStream('input.txt');

 

// 创建一个可写流

varwriterStream = fs.createWriteStream('output.txt');

 

// 管道读写操作

// 读取 input.txt文件内容,并将内容写入到 output.txt文件中

readerStream.pipe(writerStream);

 

console.log("程序执行完毕");

 

链式流,链式是通过连接输出流到另外一个流并创建多个对个流操作链的机制。链式流一般用于管道操作。

例如:

var fs= require("fs");

varzlib = require('zlib');

 

// 压缩 input.txt文件为 input.txt.gz

fs.createReadStream('input.txt')

  .pipe(zlib.createGzip())

  .pipe(fs.createWriteStream('input.txt.gz'));

 

console.log("文件压缩完成。");

解压缩:

var fs= require("fs");

varzlib = require('zlib');

 

// 解压 input.txt.gz文件为 input.txt

fs.createReadStream('input.txt.gz')

  .pipe(zlib.createGunzip())

  .pipe(fs.createWriteStream('input.txt'));

 

console.log("文件解压完成。");

 

14         Node.js模块系统

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。

模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。

创建模块

在 Node.js 中,创建一个模块非常简单,创建一个 main.js 文件,代码如下:

var hello= require('./hello');

hello.world();

Node.js 提供了 exports 和 require 两个对象,其中exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

接下来我们就来创建 hello.js 文件,代码如下:

exports.world = function() {  

console.log('Hello World');

}

也可以把一个对象封装到模块中。

 Node.js 中存在 4 类模块(原生模块和3种文件模块),尽管require 方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同。

 

15         Node.js 函数

在JavaScript中,一个函数可以作为另一个函数的参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。

functionsay(word) {

  console.log(word);

}

functionexecute(someFunction, value) {

  someFunction(value);

}

execute(say, "Hello");

匿名函数

可以把一个函数作为变量传递。但是我们不一定要绕这个"先定义,再传递"的圈子,我们可以直接在另一个函数的括号中定义和传递这个函数:

functionexecute(someFunction, value) {

  someFunction(value);

}

 

execute(function(word){ console.log(word) },"Hello");

15.1 HTTP函数工作

代码如下:

varhttp = require("http");

http.createServer(function(request,response) {

  response.writeHead(200,{"Content-Type": "text/plain"});

  response.write("Hello World");

  response.end();

}).listen(8888);

 

16         Node.js 路由

要为路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码。

需要查看 HTTP 请求,从中提取出请求的URL 以及 GET/POST 参数。这一功能应当属于路由还是服务器(甚至作为一个模块自身的功能)确实值得探讨,暂定其为HTTP服务器的功能。

需要的所有数据都会包含在 request 对象中,该对象作为onRequest() 回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的 Node.JS 模块,它们分别是 url 和 querystring 模块。

也可以用 querystring 模块来解析 POST 请求体中的参数。

16.1 onRequest路由

给 onRequest() 函数加上一些逻辑,用来找出浏览器请求的 URL 路径:

创建server.js文件内容:

varhttp = require("http");

varurl = require("url");

 

functionstart() {

  function onRequest(request, response) {

    var pathname =url.parse(request.url).pathname;

    console.log("Request for " +pathname + " received.");

    response.writeHead(200,{"Content-Type": "text/plain"});

    response.write("Hello World");

    response.end();

  }

 

  http.createServer(onRequest).listen(8888);

  console.log("Server has started.");

}

exports.start = start;

创建router.js内容如下:

functionroute(pathname) {

  console.log("About to route a requestfor " + pathname);

}

exports.route = route;

我们先来看看如何把路由和服务器整合起来。

服务器应当知道路由的存在并加以有效利用。我们当然可以通过硬编码的方式将这一依赖项绑定到服务器上,但是其它语言的编程经验告诉我们这会是一件非常痛苦的事,因此我们将使用依赖注入的方式较松散地添加路由模块。

               创建main.js,内容如下:

varserver = require("./server");

varrouter = require("./router");

server.start(router.route);

修改 server.js内容如下:

varhttp = require("http");

varurl = require("url");

 

functionstart(route) {

  function onRequest(request, response) {

    var pathname =url.parse(request.url).pathname;

    console.log("Request for " +pathname + " received.");

 

    route(pathname);

   

   

    response.writeHead(200,{"Content-Type": "text/plain"});

    response.write("Hello World");

    response.end();

  }

 

  http.createServer(onRequest).listen(8888);

  console.log("Server has started.");

}

 

exports.start = start;

 

再启动应用(node index.js,始终记得这个命令行),随后请求一个URL,你将会看到应用输出相应的信息,这表明我们的HTTP服务器已经在使用路由模块了,并会将请求的路径传递给路由。

 

17         Node.js 全局对象

JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。

在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。

在 Node.js 我们可以直接访问到global 的属性,而不需要在应用中包含它。

 

 

17.1 全局对象与全局变量

global 最根本的作用是作为全局变量的宿主。按照 ECMAScript 的定义,满足以下条件的变量是全局变量:

l   在最外层定义的变量;

l   全局对象的属性;

l   隐式定义的变量(未定义直接赋值的变量)。

当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。需要注意的是,在 Node.js 中你不可能在最外层定义变量,因为所有用户代码都是属于当前模块的,而模块本身不是最外层上下文。

注意: 永远使用 var 定义变量以避免引入全局变量,因为全局变量会污染 命名空间,提高代码的耦合风险。

17.2 __filename

__filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。

如果在模块中,返回的值是模块文件的路径。

17.3      __dirname

__dirname 表示当前执行脚本所在的目录。

17.4      setTimeout(cb, ms)

setTimeout(cb,ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。:setTimeout() 只执行一次指定函数。

返回一个代表定时器的句柄值。

17.5      clearTimeout(t)

clearTimeout( t) 全局函数用于停止一个之前通过 setTimeout() 创建的定时器。参数 t 是通过 setTimeout() 函数创建的定时器。

17.6      setInterval(cb, ms)

setInterval(cb,ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。

返回一个代表定时器的句柄值。可以使用 clearInterval(t) 函数来清除定时器。

setInterval() 方法会不停地调用函数,直到clearInterval() 被调用或窗口被关闭。

17.7      console

console 用于提供控制台标准输出,它是由 Internet Explorer 的 JScript 引擎提供的调试工具,后来逐渐成为浏览器的实施标准。

console 方法

以下为 console 对象的方法:

序号

方法 & 描述

1

console.log([data][, ...])
向标准输出流打印字符并以换行符结束。该方法接收若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。

2

console.info([data][, ...])
该命令的作用是返回信息性消息,这个命令与console.log差别并不大,除了在chrome中只会输出文字外,其余的会显示一个蓝色的惊叹号。

3

console.error([data][, ...])
输出错误消息的。控制台在出现错误时会显示是红色的叉子。

4

console.warn([data][, ...])
输出警告消息。控制台出现有黄色的惊叹号。

5

console.dir(obj[, options])
用来对一个对象进行检查(inspect),并以易于阅读和打印的格式显示。

6

console.time(label)
输出时间,表示计时开始。

7

console.timeEnd(label)
结束时间,表示计时结束。

8

console.trace(message[, ...])
当前执行的代码在堆栈中的调用路径,这个测试函数运行很有帮助,只要给想测试的函数里面加入 console.trace 就行了。

9

console.assert(value[, message][, ...])
用于判断某个表达式或变量是否为真,接收两个参数,第一个参数是表达式,第二个参数是字符串。只有当第一个参数为false,才会输出第二个参数,否则不会有任何结果。

17.8      process

process 是一个全局变量,即global 对象的属性。

它用于描述当前Node.js 进程状态的对象,提供了一个与操作系统的简单接口。在写本地命令行程序的时候,少不了要和它打交道。下面将会介绍 process 对象的一些最常用的成员方法。

序号

事件 & 描述

1

exit
当进程准备退出触发。

2

beforeExit
node清空事件循,并且有其他安排触发个事件。通常来说当没程安排 node 退出,但是 'beforeExit'听器可以异步用, node 就会继续执行。

3

uncaughtException
一个异常冒泡回到事件循,触发个事件。如果异常添加了视器,默的操作(打印堆跟踪信息并退出)就不会发生。

4

Signal 事件
当进程接收到信号就触发。信号列表准的 POSIX 信号名,如 SIGINTSIGUSR1等。

示例代码如下:

process.on('exit',function(code) {

  // 以下代码永远不会执行

  setTimeout(function() {

    console.log("该代码不会执行");

  }, 0);

  console.log('退出码为:', code);

});

console.log("程序执行结束");

17.8.1 退出状态码

退出状态码如下所示:

状态码

&描述

1

Uncaught Fatal Exception
有未捕异常,并且有被域或 uncaughtException处理函处理。

2

Unused
保留

3

Internal JavaScript Parse Error
JavaScript
的源启动 Node引起解析错误。非常罕见,会在 Node 才会有。

4

Internal JavaScript Evaluation Failure
JavaScript
的源启动 Node程,返回函。非常罕见,会在 Node 才会有。

5

Fatal Error
V8
里致命的不可恢复的错误。通常会打印到 stderr FATAL ERROR

6

Non-function Internal Exception Handler
未捕异常,部异常处理函不知何设置on-function,并且不能被用。

7

Internal Exception Handler Run-Time Failure
未捕的异常,并且异常处理函处理自己出了异常。例如,如果 process.on('uncaughtException') domain.on('error')出了异常。

8

Unused
保留

9

Invalid Argument
可能是了未知的参,或者的参数没有值。

10

Internal JavaScript Run-Time Failure
JavaScript
的源启动 Node时抛错误,非常罕见,会在 Node 才会有。

12

Invalid Debug Argument 
设置了参--debug/ --debug-brk,但是选择错误端口。

128

Signal Exits
如果 Node接收到致命信号,比如SIGKILL SIGHUP,那么退出代就是128加信号代准的 Unix 做法,退出信号代放在高位。

 

17.8.2 Process 属性

Process 提供了很多有用的属性,便于我们更好的控制系统的交互:

序号.

属性 & 描述

1

stdout
准输出流。

2

stderr
错误流。

3

stdin
准输入流。

4

argv
argv
属性返回一个数组,由命令行行脚本的各个参数组成。它的第一个成总是node,第二个成是脚本文件名,其余成是脚本文件的参

5

execPath
返回前脚本的 Node制文件的绝对

6

execArgv
返回一个数组,成是命令行下行脚本,在Node行文件与脚本文件之间的命令行参

7

env
返回一个象,成员为当 shell境变量

8

exitCode
程退出的代,如果程优通 process.exit() 退出,不需要指定退出

9

version
Node
的版本,比如v0.10.18

10

versions
一个属性,包含了 node的版本和依.

11

config
一个包含用来编译当 node行文件的 javascript配置选项象。它与运行 ./configure脚本生成的 "config.gypi"文件相同。

12

pid
程的程号。

13

title
程名,默"node",可以自定义值。

14

arch
CPU的架构:'arm''ia32'或者 'x64'

15

platform
运行程序所在的平台系统 'darwin', 'freebsd', 'linux', 'sunos' 'win32'

16

mainModule
require.main
的备方法。不同点,如果主模块在运行改变,require.main可能会继续返回老的模块。可以认为两者引用了同一个模块。

 

17.8.3 方法参考手册

Process 提供了很多有用的方法,便于我们更好的控制系统的交互:

序号

方法 & 描述

1

abort()
这将导 node触发 abort事件。会 node退出并生成一个核心文件。

2

chdir(directory)
改变前工作程的目,如果操作失败抛出异常。

3

cwd()
返回程的工作目

4

exit([code])
使用指定的 code程。如果忽略,会使用 code 0

5

getgid()
程的群组标识(参见 getgid(2))。取到得 id,而不是名字。
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

6

setgid(id)
设置程的群组标识(参见 setgid(2))。可以接收 ID 或者群名。如果指定了群名,会阻塞等待解析为数 ID
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

7

getuid()
程的用户标识(参见 getuid(2))字的用户 id,不是用户名。
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

8

setuid(id)
设置程的用户标识(参见setuid(2))。接收 ID或字符串名字。果指定了群名,会阻塞等待解析为数 ID
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

9

getgroups()
返回程的群 iD数组POSIX系统有保一定有,但是 node.js有。
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

10

setgroups(groups)
设置程的群 ID是授操作,所有你需要有 root 限,或者有 CAP_SETGID能力。
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

11

initgroups(user, extra_group)
/etc/group,并初始化群组访问列表,使用成所在的所有群是授操作,所有你需要有 root 限,或者有 CAP_SETGID能力。
注意:个函数仅 POSIX平台上可用(例如,非Windows Android)

12

kill(pid[, signal])
发送信号给进. pidid,并且 signal是发送的信号的字符串描述。信号名是字符串,比如 'SIGINT' 'SIGHUP'。如果忽略,信号会是 'SIGTERM'

13

memoryUsage()
返回一个象,描述了 Node程所用的况,

14

nextTick(callback)
一旦前事件循环结束,用回到函

15

umask([mask])
设置或程文件的掩。子程从父承掩。如果mask有效,返回的掩。否,返回前掩

16

uptime()
返回 Node已经运行的秒

17

hrtime()
返回程的高分辨间,形式 [seconds, nanoseconds]数组。它是相去的任意事件。值与日期无,因此不受钟漂移的影响。主要用途是可以通精确的间间隔,衡量程序的性能。
你可以之前的给当前的 process.hrtime() ,会返回两者间的间差,用基准和间间隔。

18          Node.js 常用工具

util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能过于精简的不足。

18.1      util.inherits

util.inherits(constructor,superConstructor)是一个实现对象间原型继承的函数。

JavaScript的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有提供对象继承的语言级别特性,而是通过原型复制来实现的。

               代码内容如下:

varutil = require('util');

functionBase() {

    this.name = 'base';

    this.base = 1991;

    this.sayHello = function() {

    console.log('Hello ' + this.name);

    };

}

Base.prototype.showName= function() {

    console.log(this.name);

};

functionSub() {

    this.name = 'sub';

}

util.inherits(Sub,Base);

varobjBase = new Base();

objBase.showName();

objBase.sayHello();

console.log(objBase);

varobjSub = new Sub();

objSub.showName();

//objSub.sayHello();

console.log(objSub);

定义了一个基础对象Base 和一个继承自Base 的Sub,Base 有三个在构造函数 内定义的属性和一个原型中定义的函数,通过util.inherits 实现继承。

注意:Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属性和 sayHello 函数都没有被 Sub 继承。同时,在原型中定义的属性不会被console.log 作为对象的属性输出。

18.2      util.inspect

util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象。

showHidden 是一个可选参数,如果值为true,将会输出更多隐藏信息。

depth 表示最大递归的层数,如果对象很复杂,你可以指定层数以控制输出信息的多少。如果不指定depth,默认会递归2层,指定为 null 表示将不限递归层数完整遍历对象。如果color 值为 true,输出格式将会以ANSI 颜色编码,通常用于在终端显示更漂亮的效果。

特别要指出的是,util.inspect 并不会简单地直接把对象转换为字符串,即使该对 象定义了toString 方法也不会调用。

18.3      util.isArray(object)

如果给定的参数"object" 是一个数组返回true,否则返回false。

18.4      util.isRegExp(object)

如果给定的参数"object" 是一个正则表达式返回true,否则返回false。

18.5      util.isDate(object)

如果给定的参数"object" 是一个日期返回true,否则返回false。

18.6      util.isError(object)

如果给定的参数"object" 是一个错误对象返回true,否则返回false。

19          Node.js 文件系统

Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)

19.1      异步和同步

Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。

异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。

建议用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。

19.2 打开文件

在异步模式下打开文件的语法格式:

fs.open(path, flags[, mode], callback)

参数使用说明如下:

l   path - 文件的路径。

l   flags - 文件打开的行为。具体值详见下文。

l   mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。

l   callback - 回调函数,带有两个参数如:callback(err, fd)。

19.3 获取文件信息

获取文件信息,通过异步模式获取文件信息的语法格式:

 fs.stat(path,callback)

 

19.4 写入文件

异步模式下写入文件的语法格式:

fs.writeFile(file, data[, options],callback)

19.5 读取文件

语法,异步模式下读取文件的语法格式:

fs.read(fd, buffer, offset, length,position, callback)

19.6      关闭文件

异步模式下关闭文件的语法格式:

fs.close(fd, callback)

19.7      文件模块方法参考手

以下为 Node.js 文件模块相同的方法列表:

序号

方法 & 描述

1

fs.rename(oldPath, newPath, callback)
异步 rename().数没有参,但可能出异常。

2

fs.ftruncate(fd, len, callback)
异步 ftruncate().数没有参,但可能出异常。

3

fs.ftruncateSync(fd, len)
同步 ftruncate()

4

fs.truncate(path, len, callback)
异步 truncate().数没有参,但可能出异常。

5

fs.truncateSync(path, len)
同步 truncate()

6

fs.chown(path, uid, gid, callback)
异步 chown().数没有参,但可能出异常。

7

fs.chownSync(path, uid, gid)
同步 chown()

8

fs.fchown(fd, uid, gid, callback)
异步 fchown().数没有参,但可能出异常。

9

fs.fchownSync(fd, uid, gid)
同步 fchown()

10

fs.lchown(path, uid, gid, callback)
异步 lchown().数没有参,但可能出异常。

11

fs.lchownSync(path, uid, gid)
同步 lchown()

12

fs.chmod(path, mode, callback)
异步 chmod().数没有参,但可能出异常。

13

fs.chmodSync(path, mode)
同步 chmod().

14

fs.fchmod(fd, mode, callback)
异步 fchmod().数没有参,但可能出异常。

15

fs.fchmodSync(fd, mode)
同步 fchmod().

16

fs.lchmod(path, mode, callback)
异步 lchmod().数没有参,但可能出异常。Only available on Mac OS X.

17

fs.lchmodSync(path, mode)
同步 lchmod().

18

fs.stat(path, callback)
异步 stat().有两个参 err, statsstats fs.Stats象。

19

fs.lstat(path, callback)
异步 lstat().有两个参 err, statsstats fs.Stats象。

20

fs.fstat(fd, callback)
异步 fstat().有两个参 err, statsstats fs.Stats象。

21

fs.statSync(path)
同步 stat().返回 fs.Stats的实例。

22

fs.lstatSync(path)
同步 lstat().返回 fs.Stats的实例。

23

fs.fstatSync(fd)
同步 fstat().返回 fs.Stats的实例。

24

fs.link(srcpath, dstpath, callback)
异步 link().数没有参,但可能出异常。

25

fs.linkSync(srcpath, dstpath)
同步 link().

26

fs.symlink(srcpath, dstpath[, type], callback)
异步 symlink().数没有参,但可能出异常。 type 可以设置 'dir', 'file', 'junction' (认为 'file')

27

fs.symlinkSync(srcpath, dstpath[, type])
同步 symlink().

28

fs.readlink(path, callback)
异步 readlink().有两个参 err, linkString

29

fs.realpath(path[, cache], callback)
异步 realpath().有两个参 err, resolvedPath

30

fs.realpathSync(path[, cache])
同步 realpath()。返回绝对

31

fs.unlink(path, callback)
异步 unlink().数没有参,但可能出异常。

32

fs.unlinkSync(path)
同步 unlink().

33

fs.rmdir(path, callback)
异步 rmdir().数没有参,但可能出异常。

34

fs.rmdirSync(path)
同步 rmdir().

35

fs.mkdir(path[, mode], callback)
S
异步 mkdir(2).数没有参,但可能出异常。 mode defaults to 0777.

36

fs.mkdirSync(path[, mode])
同步 mkdir().

37

fs.readdir(path, callback)
异步 readdir(3).取目容。

38

fs.readdirSync(path)
同步 readdir().返回文件数组列表。

39

fs.close(fd, callback)
异步 close().数没有参,但可能出异常。

40

fs.closeSync(fd)
同步 close().

41

fs.open(path, flags[, mode], callback)
异步打文件。

42

fs.openSync(path, flags[, mode])
同步 version of fs.open().

43

fs.utimes(path, atime, mtime, callback)

44

fs.utimesSync(path, atime, mtime)
修改文件间戳,文件通指定的文件路

45

fs.futimes(fd, atime, mtime, callback)

46

fs.futimesSync(fd, atime, mtime)
修改文件间戳,通文件描述符指定。

47

fs.fsync(fd, callback)
异步 fsync.数没有参,但可能出异常。

48

fs.fsyncSync(fd)
同步 fsync.

49

fs.write(fd, buffer, offset, length[, position], callback)
将缓区内入到通文件描述符指定的文件。

50

fs.write(fd, data[, position[, encoding]], callback)
文件描述符 fd入文件容。

51

fs.writeSync(fd, buffer, offset, length[, position])
同步版的 fs.write()

52

fs.writeSync(fd, data[, position[, encoding]])
同步版的 fs.write().

53

fs.read(fd, buffer, offset, length, position, callback)
文件描述符 fd取文件容。

54

fs.readSync(fd, buffer, offset, length, position)
同步版的 fs.read.

55

fs.readFile(filename[, options], callback)
异步取文件容。

56

fs.readFileSync(filename[, options])<="" td="">

57

fs.writeFile(filename, data[, options], callback)
异步入文件容。

58

fs.writeFileSync(filename, data[, options])
同步版的 fs.writeFile

59

fs.appendFile(filename, data[, options], callback)
异步追加文件容。

60

fs.appendFileSync(filename, data[, options])
The
同步 version of fs.appendFile.

61

fs.watchFile(filename[, options], listener)
查看文件的修改。

62

fs.unwatchFile(filename[, listener])
停止查看 filename的修改。

63

fs.watch(filename[, options][, listener])
查看 filename的修改,filename可以是文件或目。返回 fs.FSWatcher象。

64

fs.exists(path, callback)
检测给定的路是否存在。

65

fs.existsSync(path)
同步版的 fs.exists.

66

fs.access(path[, mode], callback)
测试指定路用户限。

67

fs.accessSync(path[, mode])
同步版的 fs.access

68

fs.createReadStream(path[, options])
返回ReadStream象。

69

fs.createWriteStream(path[, options])
返回 WriteStream象。

70

fs.symlink(srcpath, dstpath[, type], callback)
异步 symlink().数没有参,但可能出异常。

 

20          Node.js GET/POST请求

在很多场景中,服务器都需要跟用户的浏览器打交道,如表单提交。

表单提交到服务器一般都使用 GET/POST 请求。

20.1 获取GET请求内容

由于GET请求直接被嵌入在路径中,URL是完整的请求路径,可以手动解析后面的内容作为GET请求的参数。

node.js 中 url 模块中的 parse 函数提供了这个功能。

代码如下:

varhttp = require('http');

varurl = require('url');

varutil = require('util');

 

http.createServer(function(req,res){

    res.writeHead(200, {'Content-Type': 'text/plain;charset=utf-8'});

    res.end(util.inspect(url.parse(req.url,true)));

}).listen(3000);

在浏览器中访问

http://localhost:3000/user?name=hello&url=www.baidu.com 然后查看返回结果。

Url {  

protocol: null,  

slashes: null,  

auth: null,  

host: null,  

port: null,  

hostname: null,  

hash: null,  

search:'?name=hello&url=www.baidu.com',  

query: { name: 'hello', url:'www.baidu.com' },  

pathname: '/user',  

path:'/user?name=hello&url=www.baidu.com',  

href:'/user?name=hello&url=www.baidu.com' }

20.2 获取 URL 的参数

我们可以使用 url.parse 方法来解析 URL 中的参数。

varhttp = require('http');

varurl = require('url');

varutil = require('util');

 

http.createServer(function(req,res){

    res.writeHead(200, {'Content-Type':'text/plain'});

 

    // 解析 url参数

    var params = url.parse(req.url,true).query;

    res.write("网站名:" + params.name);

    res.write("\n");

    res.write("网站 URL" + params.url);

    res.end();

 

}).listen(3000);

http://localhost:3000/user?name=hello&url=www.baidu.com 然后查看返回结果。

网站名:hello

网站 URL:www.baidu.com

 

20.3       POST

POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。

比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所有node.js 默认是不会解析请求体的,当你需要的时候,需要手动来做。

               代码如下:

varhttp = require('http');

varquerystring = require('querystring');

varutil=require('util');

http.createServer(function(req,res){

    // 定义了一个post变量,用于暂存请求体的信息

    var post = '';    

    // 通过reqdata事件监听函数,每当接受到请求体的数据,就累加到post变量中

    req.on('data', function(chunk){   

        post += chunk;

    });

    // end事件触发后,通过querystring.parsepost解析为真正的POST请求格式,然后向客户端返回。

    req.on('end', function(){   

        post = querystring.parse(post);

        res.end(util.inspect(post));

    });

}).listen(3000);

通过表单获取POST

varhttp = require('http');

varquerystring = require('querystring');

varpostHTML =

  '<html><head><metacharset="utf-8"><title>菜鸟教程 Node.js实例</title></head>' +

  '<body>' +

  '<form method="post">' +

  '网站名: <input name="name"><br>' +

  '网站 URL <input name="url"><br>' +

  '<input type="submit">' +

  '</form>' +

  '</body></html>';

http.createServer(function(req, res) {

  var body = "";

  req.on('data', function (chunk) {

    body += chunk;

  });

  req.on('end', function () {

    // 解析参数

    body = querystring.parse(body);

    // 设置响应头部信息及编码

    res.writeHead(200, {'Content-Type':'text/html; charset=utf8'});

    if(body.name && body.url) { //输出提交的数据

        res.write("网站名:" + body.name);

        res.write("<br>");

        res.write("网站 URL" + body.url);

    } else { // 输出表单

        res.write(postHTML);

    }

   res.end();

  });

}).listen(3000);

 

21          Node.js 工具模块

在Node.js模块库中有很多好用的模块。

序号

模块名 & 描述

1

OS 模块

提供基本的系统操作函数。

2

Path 模块

提供了处理和转换文件路的工具。

3

Net 模块

用于底层的网络通信。提供了服务端和客户端的的操作。

4

DNS 模块

用于解析域名。

5

Domain 模块

简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的。

 

22          Node.js Web 模块

Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,Web服务器的基本功能就是提供Web信息浏览服务。它只需支持HTTP协议、HTML文档格式及URL,与客户端的网络浏览器配合。

大多数 web 服务器都支持服务端的脚本语言(php、python、ruby)等,并通过脚本语言从数据库获取数据,将结果返回给客户端浏览器。

目前最主流的三个Web服务器是Apache、Nginx、IIS。

框架如下图:

l   Client - 客户端,一般指浏览器,浏览器可以通过 HTTP 协议向服务器请求数据。

l   Server - 服务端,一般指 Web 服务器,可以接收客户端请求,并向客户端发送响应数据。

l   Business - 业务层,通过 Web 服务器处理应用程序,如与数据库交互,逻辑运算,调用外部程序等。

l   Data - 数据层,一般由数据库组成。

22.1 使用 Node 创建 Web 服务器

代码如下:

varhttp = require('http');

var fs= require('fs');

varurl = require('url');

// 创建服务器

http.createServer(function (request, response) { 

   // 解析请求,包括文件名

   var pathname =url.parse(request.url).pathname;

   // 输出请求的文件名

   console.log("Request for " +pathname + " received.");

   // 从文件系统中读取请求的文件内容

   fs.readFile(pathname.substr(1), function(err, data) {

      if (err) {

         console.log(err);

         // HTTP 状态码: 404 : NOT FOUND

         // Content Type: text/plain

         response.writeHead(404,{'Content-Type': 'text/html'});

      }else{            

         // HTTP 状态码: 200 : OK

         // Content Type: text/plain

         response.writeHead(200,{'Content-Type': 'text/html'});   

         // 响应文件内容

         response.write(data.toString());       

      }

      // 发送响应数据

      response.end();

   });  

}).listen(8081);

http://localhost:8081/index.html

22.2      使用 Node Web客户端

varhttp = require('http');

// 用于请求的选项

varoptions = {

   host: 'localhost',

   port: '8081',

   path: '/index.html' 

};

// 处理响应的回调函数

varcallback = function(response){

   // 不断更新数据

   var body = '';

   response.on('data', function(data) {

      body += data;

   });

   response.on('end', function() {

      // 数据接收完成

      console.log(body);

   });

}

// 向服务端发送请求

varreq = http.request(options, callback);

req.end();

 

23          Node.js Express 框架


23.1      Express

Express 是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。

使用 Express 可以快速地搭建一个完整功能的网站。

Express 框架核心特性:

l   可以设置中间件来响应HTTP 请求。

l   定义了路由表用于执行不同的HTTP 请求动作。

l   可以通过向模板传递参数来动态渲染 HTML 页面。

23.2      Express框架实例

使用 Express 框架来输出"Hello World"。

以下实例中我们引入了 express 模块,并在客户端发起请求后,响应 "Hello World" 字符串。

创建 express_demo.js 文件,代码如下所示:

varexpress = require('express');

varapp = express();

 

app.get('/',function (req, res) {

   res.send('Hello World');

})

 

varserver = app.listen(8081, function () {

 

  var host = server.address().address

  var port = server.address().port

 

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

 

})

Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。

23.2.1 request 和 response 对象的具体介绍

Request 对象 -request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。

常见属性有:

req.app:当callback为外部文件时,用req.app访问express的实例

req.baseUrl:获取路由当前安装的URL路径

req.body / req.cookies:获得「请求主体」/Cookies

req.fresh / req.stale:判断请求是否还「新鲜」

req.hostname / req.ip:获取主机名和IP地址

req.originalUrl:获取原始请求URL

req.params:获取路由的parameters

req.path:获取请求路径

req.protocol:获取协议类型

req.query:获取URL的查询参数串

req.route:获取当前匹配的路由

req.subdomains:获取子域名

req.accepts():检查可接受的请求的文档类型

req.acceptsCharsets / req.acceptsEncodings/ req.acceptsLanguages:返回指定字符集的第一个可接受字符编码

req.get():获取指定的HTTP请求头

req.is():判断请求头Content-Type的MIME类型

Response 对象 -response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。

常见属性有:

res.app:同req.app一样

res.append():追加指定HTTP头

res.set()在res.append()后将重置之前设置的头

res.cookie(name,value [,option]):设置Cookie

opition: domain / expires / httpOnly /maxAge / path / secure / signed

res.clearCookie():清除Cookie

res.download():传送指定路径的文件

res.get():返回指定的HTTP头

res.json():传送JSON响应

res.jsonp():传送JSONP响应

res.location():只设置响应的LocationHTTP头,不设置状态码或者close response

res.redirect():设置响应的LocationHTTP头,并且设置状态码302

res.send():传送HTTP响应

res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type

res.set():设置HTTP头,传入object可以一次设置多个头

res.status():设置HTTP状态码

res.type():设置Content-Type的MIME类型

 

23.3      路由

了解了 HTTP 请求的基本应用,而路由决定了由谁(指定脚本)去响应客户端请求。

在HTTP请求中,我们可以通过路由提取出请求的URL以及GET/POST参数。

接下来我们扩展 Hello World,添加一些功能来处理更多类型的 HTTP 请求。

               代码如下:

varexpress = require('express');

varapp = express();

//  主页输出 "Hello World"

app.get('/',function (req, res) {

   console.log("主页 GET请求");

   res.send('Hello GET');

})

//  POST 请求

app.post('/',function (req, res) {

   console.log("主页 POST请求");

   res.send('Hello POST');

})

//  /del_user 页面响应

app.get('/del_user',function (req, res) {

   console.log("/del_user响应 DELETE请求");

   res.send('删除页面');

})

//  /list_user 页面 GET请求

app.get('/list_user',function (req, res) {

   console.log("/list_user GET请求");

   res.send('用户列表页面');

})

// 对页面 abcd, abxcd, ab123cd,等响应 GET请求

app.get('/ab*cd',function(req, res) {  

   console.log("/ab*cd GET请求");

   res.send('正则匹配');

})

varserver = app.listen(8081, function () {

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

 

23.4      静态文件

Express 提供了内置的中间件 express.static 来设置静态文件如:图片,CSS, JavaScript等。

可以使用 express.static 中间件来设置静态文件路径。例如,如果你将图片, CSS, JavaScript 文件放在 public 目录下,你可以这么写:

app.use(express.static('public'));

代码如下:

varexpress = require('express');

varapp = express();

app.use(express.static('public'));

app.get('/',function (req, res) {

   res.send('Hello World');

})

varserver = app.listen(8081, function () {

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

 

 

23.5      GET 方法

演示了在表单中通过 GET 方法提交两个参数,我们可以使用 server.js 文件内的 process_get 路由器来处理输入:

创建index.html如下:

<html>

<body>

<formaction="http://127.0.0.1:8081/process_get" method="GET">

FirstName: <input type="text" name="first_name">  <br>

LastName: <input type="text" name="last_name">

<inputtype="submit" value="Submit">

</form>

</body>

</html>

创建代码如下:

varexpress = require('express');

varapp = express();

app.use(express.static('public'));

app.get('/index.html',function (req, res) {

   res.sendFile( __dirname + "/" +"index.html" );

})

app.get('/process_get',function (req, res) {

   // 输出 JSON格式

   var response = {

       "first_name":req.query.first_name,

      "last_name":req.query.last_name

   };

   console.log(response);

   res.end(JSON.stringify(response));

})

varserver = app.listen(8081, function () {

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

23.6      POST方法

在表单中通过 POST 方法提交两个参数,我们可以使用 server.js 文件内的 process_post 路由器来处理输入:

               index.html内容如下:

<html>

<body>

<formaction="http://127.0.0.1:8081/process_post"method="POST">

FirstName: <input type="text" name="first_name">  <br>

LastName: <input type="text" name="last_name">

<inputtype="submit" value="Submit">

</form>

</body>

</html>

代码如下:

varexpress = require('express');

varapp = express();

varbodyParser = require('body-parser');

 

// 创建 application/x-www-form-urlencoded编码解析

varurlencodedParser = bodyParser.urlencoded({ extended: false })

 

app.use(express.static('public'));

 

app.get('/index.htm',function (req, res) {

   res.sendFile( __dirname + "/" +"index.htm" );

})

 

app.post('/process_post',urlencodedParser, function (req, res) {

 

   // 输出 JSON格式

   var response = {

      "first_name":req.body.first_name,

       "last_name":req.body.last_name

   };

   console.log(response);

   res.end(JSON.stringify(response));

})

 

varserver = app.listen(8081, function () {

 

  var host = server.address().address

  var port = server.address().port

 

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

 

})

23.7      文件上

创建一个用于上传文件的表单,使用 POST方法,表单 enctype 属性设置为 multipart/form-data

index.html内容如下:

<html>

<head>

<title>文件上传表单</title>

</head>

<body>

<h3>文件上传:</h3>

选择一个文件上传: <br />

<formaction="/file_upload" method="post"enctype="multipart/form-data">

<inputtype="file" name="image" size="50" />

<br/>

<inputtype="submit" value="上传文件" />

</form>

</body>

</html>

代码如下:

varexpress = require('express');

varapp = express();

var fs= require("fs");

varbodyParser = require('body-parser');

varmulter  = require('multer');

app.use(express.static('public'));

app.use(bodyParser.urlencoded({extended: false }));

app.use(multer({dest: '/tmp/'}).array('image'));

app.get('/index.html',function (req, res) {

   res.sendFile( __dirname + "/" +"index.html" );

})

app.post('/file_upload',function (req, res) {

   console.log(req.files[0]);  //上传的文件信息

   var des_file = __dirname + "/" +req.files[0].originalname;

   fs.readFile( req.files[0].path, function(err, data) {

        fs.writeFile(des_file, data, function(err) {

         if( err ){

              console.log( err );

         }else{

               response = {

                   message:'File uploaded successfully',

                  filename:req.files[0].originalname

              };

          }

          console.log( response );

          res.end( JSON.stringify( response ));

       });

   });

})

varserver = app.listen(8081, function () {

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

23.8      Cookie管理

可以使用中间件向 Node.js 服务器发送 cookie 信息,以下代码输出了客户端发送的 cookie 信息:

varexpress      = require('express')

varcookieParser = require('cookie-parser')

varapp = express()

app.use(cookieParser())

app.get('/',function(req, res) {

  console.log("Cookies: ",req.cookies)

})

app.listen(8081)

 

24           Node.js RESTful API

24.1 什么是 REST

REST即表述性状态传递(英文:RepresentationalState Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。

表述性状态转移是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。需要注意的是,REST是设计风格而不是标准。REST通常基于使用HTTP,URI,和XML(标准通用标记语言下的一个子集)以及HTML(标准通用标记语言下的一个应用)这些现有的广泛流行的协议和标准。REST 通常使用 JSON 数据格式。

24.2 HTTP 方法

REST 基本架构的四个方法:

l   GET - 用于获取数据。

l   PUT - 用于更新或添加数据。

l   DELETE - 用于删除数据。

l   POST - 用于添加数据。

24.3      RESTful Web Services

Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。

基于 REST 架构的 WebServices 即是 RESTful。由于轻量级以及通过 HTTP 直接传输数据的特性,Web 服务的 RESTful 方法已经成为最常见的替代方法。可以使用各种语言(比如 Java 程序、Perl、Ruby、Python、PHP 和 Javascript[包括 Ajax])实现客户端。

RESTful Web 服务通常可以通过自动客户端或代表用户的应用程序访问。但是,这种服务的简便性让用户能够与之直接交互,使用它们的 Web 浏览器构建一个 GET URL 并读取返回的内容。

24.4       RESTful

首先,创建一个 json 数据资源文件users.json

{

   "user1" : {

      "name" : "mahesh",

      "password" :"password1",

      "profession" :"teacher",

      "id": 1

   },

   "user2" : {

      "name" : "suresh",

      "password" :"password2",

      "profession" :"librarian",

      "id": 2

   },

   "user3" : {

      "name" : "ramesh",

      "password" :"password3",

      "profession" :"clerk",

      "id": 3

   }

}

基于以上数据,我们创建以下 RESTfulAPI:

序号

URI

HTTP 方法

发送

1

listUsers

GET

示所有用户列表

2

addUser

POST

JSON 字符串

添加新用户

3

deleteUser

DELETE

JSON 字符串

删除用户

4

:id

GET

示用户详细信息

 

创建RESTfulAPI listUsers,用于读取用户的信息列表:

varexpress = require('express');

varapp = express();

var fs= require("fs");

 

app.get('/listUsers',function (req, res) {

   fs.readFile( __dirname + "/" +"users.json", 'utf8', function (err, data) {

       console.log( data );

       res.end( data );

   });

})

varserver = app.listen(8081, function () {

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

 

24.4.1  添加用户

以下代码,我们创建了 RESTful API addUser, 用于添加新的用户数据,server.js 文件代码如下所示:

varexpress = require('express');

varapp = express();

var fs= require("fs");

//添加的新用户数据

varuser = {

   "user4" : {

      "name" : "mohit",

      "password" :"password4",

      "profession" :"teacher",

      "id": 4

   }

}

app.get('/addUser',function (req, res) {

   // 读取已存在的数据

   fs.readFile( __dirname + "/" +"users.json", 'utf8', function (err, data) {

       data = JSON.parse( data );

       data["user4"] =user["user4"];

       console.log( data );

       res.end( JSON.stringify(data));

   });

})

varserver = app.listen(8081, function () {

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

24.4.2  删除用户

以下代码,我们创建了 RESTfulAPI deleteUser,用于删除指定用户的详细信息,以下实例中,用户 id 为 2,server.js 文件代码如下所示:

varexpress = require('express');

varapp = express();

var fs= require("fs");

 

var id= 2;

 

app.get('/deleteUser',function (req, res) {

 

   // First read existing users.

   fs.readFile( __dirname + "/" +"users.json", 'utf8', function (err, data) {

       data = JSON.parse( data );

       delete data["user" + 2];

      

       console.log( data );

       res.end( JSON.stringify(data));

   });

})

 

varserver = app.listen(8081, function () {

 

  var host = server.address().address

  var port = server.address().port

  console.log("应用实例,访问地址为 http://%s:%s", host, port)

 

})

 

25          Node.js 多进程

Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,有助于在多核 cpu 的系统上创建多个子进程,从而提高性能。

每个子进程总是带有三个流对象:child.stdin,child.stdout 和child.stderr。他们可能会共享父进程的 stdio 流,或者也可以是独立的被导流的流对象。

Node 提供了 child_process 模块来创建子进程,方法有:

l   exec - child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。

l   spawn - child_process.spawn 使用指定的命令行参数创建新进程。

l   fork - child_process.fork 是 spawn()的特殊形式,用于在子进程中运行的模块,如 fork('./son.js') 相当于 spawn('node', ['./son.js']) 。与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信。

 

25.1      exec()方法

child_process.exec使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。

语法如下所示:

child_process.exec(command[, options],callback)

示例如下:

constfs = require('fs');

constchild_process = require('child_process');

for(vari=0; i<3; i++) {

   var workerProcess = child_process.exec('nodesupport.js '+i,

      function (error, stdout, stderr) {

         if (error) {

            console.log(error.stack);

            console.log('Error code:'+error.code);

            console.log('Signal received:'+error.signal);

         }

         console.log('stdout: ' + stdout);

         console.log('stderr: ' + stderr);

      });

      workerProcess.on('exit', function (code){

      console.log('子进程已退出,退出码 '+code);

   });

}

需要新建一个support.js文件,空白的也行。

 

25.2      spawn()方法

child_process.spawn使用指定的命令行参数创建新进程,语法格式如下:

child_process.spawn(command[,args][, options])

代码如下:

constfs = require('fs');

constchild_process = require('child_process');

for(vari=0; i<3; i++) {

   var workerProcess =child_process.spawn('node', ['support.js', i]);

   workerProcess.stdout.on('data', function(data) {

      console.log('stdout: ' + data);

   });

   workerProcess.stderr.on('data', function(data) {

      console.log('stderr: ' + data);

   });

   workerProcess.on('close', function (code) {

      console.log('子进程已退出,退出码 '+code);

   });

}

 

 

 

25.3      fork方法

child_process.fork是 spawn() 方法的特殊形式,用于创建进程,语法格式如下:

child_process.fork(modulePath[, args][,options])

constfs = require('fs');

constchild_process = require('child_process');

for(vari=0; i<3; i++) {

   var worker_process =child_process.fork("support.js", [i]);   

 

   worker_process.on('close', function (code) {

      console.log('子进程已退出,退出码 ' + code);

   });

}

 

 

26          Node.js JXcore 打包

Node.js 是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。

JXcore 是一个支持多线程的Node.js 发行版本,基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。

 

27          Node.js 连接 MySQL

代码如下:

varmysql      = require('mysql');

varconnection = mysql.createConnection({

  host    : 'localhost',

  user    : 'root',

  password : '123456',

  database : 'test'

});

 

connection.connect();

 

connection.query('SELECT1 + 1 AS solution', function (error, results, fields) {

  if (error) throw error;

  console.log('The solution is: ',results[0].solution);

});

 

27.1.1  库连接参数说明:

 

描述

host

主机地址(默localhost

user

用户名

password

port

端口号(默3306

database

charset

接字符集(默'UTF8_GENERAL_CI',注意字符集的字母都要大

localAddress

IP用于TCP接(可

socketPath

接到unix域路使用 host port会被忽略

timezone

时区(默'local'

connectTimeout

接超(默:不限制;位:毫秒)

stringifyObjects

是否序列化

typeCast

是否列值本地JavaScript类型值(默true

queryFormat

自定义query句格式化方法

supportBigNumbers

支持bigintdecimal类型列,需要设此optiontrue(默false

bigNumberStrings

supportBigNumbersbigNumberStrings启用强制bigintdecimal列以JavaScript字符串类型返回(默false

dateStrings

强制timestamp,datetime,data类型以字符串类型返回,而不是JavaScript Date类型(默false

debug

调试(默false

multipleStatements

是否一个query中有多个MySQL(默false

flags

用于修改

ssl

使用ssl(与crypto.createCredenitals格式一至)或一个包含ssl配置文件名的字符串,目前只捆Amazon RDS的配置文件

 

 

28          Node.js 连接 MongoDB

MongoDB是一种文档导向数据库管理系统。

插入数据代码如下:

varMongoClient = require('mongodb').MongoClient;

varDB_CONN_STR = 'mongodb://localhost:27017/runoob'; #数据库为 runoob

 

varinsertData = function(db, callback) { 

    //连接到表 site

    var collection = db.collection('site');

    //插入数据

    var data = [{"name":"菜鸟教程","url":"www.runoob.com"},{"name":"菜鸟工具","url":"c.runoob.com"}];

    collection.insert(data, function(err,result) {

        if(err)

        {

            console.log('Error:'+ err);

            return;

        }    

        callback(result);

    });

}

 

MongoClient.connect(DB_CONN_STR,function(err, db) {

    console.log("连接成功!");

    insertData(db, function(result) {

        console.log(result);

        db.close();

    });

});

 

29         jax

AJAX = Asynchronous JavaScript and XML(异步的JavaScript 和 XML)。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

 

30         前端框架

(jQuery/YUI/ExtJS/RequireJS/BootStrap之类)

 

 

 

31         数据库

31.1 mysql

 

31.2 mongodb

 

31.3 redis

 

31.4 memcached

 

32         参考

Java与javascript关系

http://www.php.cn/toutiao-356681.html

Node.js

http://www.runoob.com/nodejs/nodejs-tutorial.html

参考RESTful

http://www.runoob.com/w3cnote/restful-architecture.html

 

 

 

 

 

 

 

 

 


原创粉丝点击