Nodejs学习笔记

安装:http://www.runoob.com/nodejs/nodejs-install-setup.html

介绍:

Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js 不是一个 JavaScript 框架,不同于CakePHPDjangoRails。Node.js 更不是浏览器端的库,不能与 jQuery、ExtJS 相提并论。Node.js 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHPPythonPerlRuby 等服务端语言平起平坐的脚本语言

Node.js 回调函数

Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。

回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。

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

 

阻塞代码示例:

var fs=require('fs');
var data=fs.readFileSync('1.txt');
console.log(data.toString());
console.log('程序执行完成');

 

非阻塞代码实例

var fs = require('fs');
fs.readFile('1.txt', function (err, data) {
    if (err)  return console.error(err);
    console.log(data.toString()+"1");
})
console.log('程序执行完成');

 

Node.js 事件循环

Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。

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

 

事件驱动程序

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

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

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

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

 

 

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

 

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

var events = require('events');// 引入 events 模块
var eventEmitter = new events.EventEmitter();// 创建 eventEmitter 对象
var connectHandler = function connected() {// 创建事件处理程序
    console.log('连接成功。');
    eventEmitter.emit('data_received'); // 触发 data_received 事件
}
eventEmitter.on('connection', connectHandler);// 绑定 connection 事件处理程序
eventEmitter.on('data_received', function(){// 使用匿名函数绑定 data_received 事件
    console.log('数据接收成功。');
});
eventEmitter.emit('connection');// 触发 connection 事件
console.log("程序执行完毕。");

 

 

Node 应用程序是如何工作的?

在 Node 应用程序中,执行异步操作的函数将回调函数作为最后一个参数, 回调函数接收错误对象作为第一个参数。

例子:

var fs = require("fs");
fs.readFile('1.txt', function (err, data) {
    if (err){
        console.log(err.stack);
        return;
    }
    console.log(data.toString());
});
console.log("程序执行完毕");

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

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

 

Node.js EventEmitter

Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。

Node.js 里面的许多对象都会分发事件:一个 net.Server 对象会在每次有新连接时触发一个事件, 一个 fs.readStream 对象会在文件被打开的时候触发一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。

 

EventEmitter 类

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

你可以通过require("events");来访问该模块。

 

var events = require('events');// 引入 events 模块
var eventEmitter = new events.EventEmitter();// 创建 eventEmitter 对象

 

EventEmitter 对象如果在实例化时发生错误,会触发 error 事件。当添加新的监听器时,newListener 事件会触发,当监听器被移除时,removeListener 事件被触发。

下面我们用一个简单的例子说明 EventEmitter 的用法:

var EventEmitter=require('events').EventEmitter;
var event=new EventEmitter();
event.on('some_event',function () {
    console.log('事件触发');
})
setTimeout(function () {//定时器
    event.emit('some_event');
},1000);//一秒后执行

 

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

 

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

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

例子:

var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
    console.log('listener1', arg1, arg2);
});
emitter.on('someEvent', function(arg1, arg2) {
    console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');

 

 

emitter为时间someEvent注册了两个事件监听器,然后触发someEvent事件.谁在前面就谁先执行

 

EventEmitter 提供了多个属性,如 on 和 emit。on 函数用于绑定事件函数,emit 属性用于触发一个事件。接下来我们来具体看下 EventEmitter 的属性介绍。

 

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

 

on(event, listener)       为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。

 

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

 

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

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

 

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

 

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

 

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

 

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

 

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

 

事件:

newListener    

参数:

event - 字符串,事件名称   

listener - 处理事件函数

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

 

 

removeListener

参数:

event - 字符串,事件名称

listener - 处理事件函数

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

 

注意点:

1、eventEmitter.on()与eventEmitter.addListener()没有区别,且一个事件可以绑定多个回调函数;

2、若事件队列中出现一个未绑定事件则触发error事件,若未绑定 error事件则程序抛出异常结束执行

3removeListener('connection',callback); 此处参数 callback 必须和监听器中的回调函数是同一个,否则不生效。

 

示例:

var events = require('events');
var eventEmitter = new events.EventEmitter();
// 监听器 #1
var listener1 = function listener1() {
    console.log('监听器 listener1 执行。');
}
// 监听器 #2
var listener2 = function listener2() {
    console.log('监听器 listener2 执行。');
}
// 绑定 connection 事件,处理函数为 listener1
eventEmitter.addListener('connection', listener1);
// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection', listener2);

//返回监听总数
var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
// 处理 connection 事件
eventEmitter.emit('connection');
// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");
// 触发连接事件
eventEmitter.emit('connection');
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
console.log("程序执行完毕。");

 

 

以上代码就是上方的方法的证明.

 

error 事件

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

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

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

var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');

 

 

继承 EventEmitter

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

为什么要这样做呢?原因有两点:

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

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

 

 

Node.js Buffer(缓冲区)

在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

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

创建 Buffer 类

Buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0

Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据

Buffer.allocUnsafeSlow(size)

Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)

Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。

Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例

Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例

写入缓冲区

语法

写入 Node 缓冲区的语法如下所示:

buf.write(string[, offset[, length]][, encoding]);

参数:

string - 写入缓冲区的字符串。

offset - 缓冲区开始写入的索引值,默认为 0 。

length - 写入的字节数,默认为 buffer.length

encoding - 使用的编码。默认为 'utf8' 。

 

根据 encoding 的字符编码写入 string 到 buf 中的 offset 位置。 length 参数是写入的字节数。 如果 buf 没有足够的空间保存整个字符串,则只会写入 string 的一部分。 只部分解码的字符不会被写入。

 

返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串。

 

从缓冲区读取数据

语法:

buf.toString([encoding[, start[, end]]])

参数:

encoding - 使用的编码。默认为 'utf8' 。

start - 指定开始读取的索引位置,默认为 0。

end - 结束位置,默认为缓冲区的末尾。

 

代码示例:

buf = Buffer.alloc(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

 

将 Buffer 转换为 JSON 对象

语法:

buf.toJSON();

 

当字符串化一个 Buffer 实例时,JSON.stringify() 会隐式地调用该 toJSON()

JSON.parse()【从一个字符串中解析出json对象】

JSON.stringify()【从一个对象中解析出字符串】

 

示例:

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf); 
// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);
const copy = JSON.parse(json, (key, value) => {
    return value && value.type === 'Buffer' ?
        Buffer.from(value.data) : value;
});
console.log(copy);// 输出: <Buffer 01 02 03 04 05>

 

缓冲区合并

语法

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

Buffer.concat(list[, totalLength])

参数:

list - 用于合并的 Buffer 对象数组列表。

totalLength - 指定合并后Buffer对象的总长度。

返回值

返回一个多个成员合并的新 Buffer 对象。

var buffer1 = Buffer.from(('菜鸟教程'));
var buffer2 = Buffer.from(('www.runoob.com'));
var buffer3 = Buffer.concat([buffer1,buffer2]);//合并
console.log("buffer3 内容: " + buffer3.toString());

缓冲区比较

语法

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

buf.compare(otherBuffer);

参数:

otherBuffer - 与 buf 对象比较的另外一个 Buffer 对象。

 

返回值

返回一个数字,表示 buf 在 otherBuffer 之前,之后或相同。

 

示例:

var buffer1 = Buffer.from('ABC');
var buffer2 = Buffer.from('ABCD');
var result = buffer1.compare(buffer2);
if(result < 0) {
    console.log(buffer1 + "  " + buffer2 + "之前");
}else if(result == 0){
    console.log(buffer1 + "  " + buffer2 + "相同");
}else {
    console.log(buffer1 + "  " + buffer2 + "之后");
}

 

拷贝缓冲区

语法:

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

参数

targetBuffer - 要拷贝的 Buffer 对象。

targetStart - 数字, 可选, 默认: 0

sourceStart - 数字, 可选, 默认: 0

sourceEnd - 数字, 可选, 默认: buffer.length

 

示例:

var buf1 = Buffer.from('abcdefghijkl');
var buf2 = Buffer.from('RUNOOB');
// buf2 插入到 buf1 指定位置上
buf2.copy(buf1, 2);
console.log(buf1.toString());

 

缓冲区裁剪

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

参数

start - 数字, 可选, 默认: 0

end - 数字, 可选, 默认: buffer.length

返回值

返回一个新的缓冲区,它和旧缓冲区指向同一块内存,但是从索引 start 到 end 的位置剪切。

var buffer1 = Buffer.from('runoob');
// 剪切缓冲区
var buffer2 = buffer1.slice(0,2);
console.log("buffer2 content: " + buffer2.toString());

 

裁剪功能返回的实际是原始缓存区 buffer 或者一部分,操作的是与原始 buffer 同一块内存区域。

Node.js Buffer 模块常用的方法:

https://www.runoob.com/nodejs/nodejs-buffer.html

 

 

Node.js Stream(流)

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

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

Readable - 可读操作。

Writable - 可写操作。

Duplex - 可读可写操作.

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

 

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

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

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

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

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

 

从流中读取数据

示例:

//重流中读取数据
var fs = require("fs");
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('1.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");
var data = '菜鸟教程官网地址:www.runoob.com';
// 创建一个可以写入的流,写入到文件 1.txt
var writerStream = fs.createWriteStream('1.txt');
// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');
// 标记文件末尾
writerStream.end();
// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
    console.log("写入完成。");
});
writerStream.on('error', function(err){
    console.log(err.stack);
});
console.log("程序执行完毕");

管道流

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

以下实例我们通过读取一个文件内容并将内容写入到另外一个文件中。

var fs = require("fs");
// 创建一个可读流
var readerStream = fs.createReadStream('1.txt');
// 创建一个可写流
var writerStream = fs.createWriteStream('output.txt');
// 管道读写操作
// 读取 1.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);
console.log("程序执行完毕");

 

结果为生成了一个新文件,名为output.txt  内容和1.txt一致

 

链式流

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

接下来我们就是用管道和链式来压缩和解压文件。

 

压缩示例:

var fs = require("fs");var zlib = require('zlib');
// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream('1.txt')
    .pipe(zlib.createGzip())
    .pipe(fs.createWriteStream('1.txt.gz'));
console.log("文件压缩完成。");

 

解压示例:

var fs = require("fs");var zlib = require('zlib');
// 解压 1.txt.gz 文件为 2.txt
fs.createReadStream('1.txt.gz')
    .pipe(zlib.createGunzip())
    .pipe(fs.createWriteStream('2.txt'));
console.log("文件解压完成。");

 

Node.js模块系统

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

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

创建模块

function Hello() {
    var name;
    this.setName = function (thyname) {
        name = thyname;
    };
    this.sayHello = function () {
        console.log('hello' + name);
    };
}
module.exports=Hello;

这样就能直接获取这个对象了;

 

调用:

var Hello=require('./模块系统');
hello=new Hello();
hello.setName('123');
hello.sayHello();

 

Node.js 函数

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

Node.js中函数的使用与Javascript类似,举例来说,你可以这样做:

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

 

以上代码中,我们把 say 函数作为execute函数的第一个变量进行了传递。这里传递的不是 say 的返回值,而是 say 本身!

say 就变成了execute 中的本地变量 someFunction ,execute可以通过调用 someFunction() (带括号的形式)来使用 say 函数。当然,因为 say 有一个变量, execute 在调用 someFunction 时可以传递这样一个变量。

 

 

函数传递是怎么样让HTTP服务器工作的:
var http = require("http");
http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
}).listen(8888);

 

也可以写成:

var http = require("http");
function onRequest(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
}
http.createServer(onRequest).listen(8888);

 

Node.js 路由

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

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

 

首先创建server.js

var http = require("http");
var url = require("url");
function start(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;

 

创建router.js

function route(pathname) {
    console.log("About to route a request for " + pathname);
}
exports.route = route;

 

创建index.js

var server = require("./server");
var router = require("./router");
server.start(router.route);

 

启动服务器:

 

 

访问 http://127.0.0.1:8888/

 

 

Node.js 全局对象

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

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

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

 

全局对象与全局变量

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

  • 在最外层定义的变量;
  • 全局对象的属性;
  • 隐式定义的变量(未定义直接赋值的变量)。

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

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

 

__filename

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

 

示例:

console.log(__filename);

效果:

 

__dirname

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

 

示例:

console.log(__dirname);

 

 

process

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

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

1

exit
当进程准备退出时触发。

2

beforeExit
当 node 清空事件循环,并且没有其他安排时触发这个事件。通常来说,当没有进程安排时 node 退出,

但是 'beforeExit' 的监听器可以异步调用,这样 node 就会继续执行。

3

uncaughtException
当一个异常冒泡回到事件循环,触发这个事件。如果给异常添加了监视器,默认的操作(打印堆栈跟踪信息并退出)

就不会发生。

4

Signal 事件
当进程接收到信号时就触发。信号列表详见标准的 POSIX 信号名,如 SIGINT、SIGUSR1 等。

 

退出状态码:

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 做法,退出信号代码放在高位。

 

属性:

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可能会继续返回老的模块。

可以认为,这两者引用了同一个模块。

 

方法:

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])
发送信号给进程. pid 是进程id,并且 signal 是发送的信号的字符串描述。

信号名是字符串,比如 'SIGINT' 或 'SIGHUP'。如果忽略,信号会是 'SIGTERM'。

13

memoryUsage()
返回一个对象,描述了 Node 进程所用的内存状况,单位为字节。

14

nextTick(callback)
一旦当前事件循环结束,调用回调函数。

15

umask([mask])
设置或读取进程文件的掩码。子进程从父进程继承掩码。如果mask 参数有效,返回旧的掩码。否则,返回当前掩码。

16

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

17

hrtime()
返回当前进程的高分辨时间,形式为 [seconds, nanoseconds]数组。

它是相对于过去的任意事件。该值与日期无关,因此不受时钟漂移的影响。

主要用途是可以通过精确的时间间隔,来衡量程序的性能。
你可以将之前的结果传递给当前的 process.hrtime() ,会返回两者间的时间差,用来基准和测量时间间隔。

 

 

Node.js 常用工具

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

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);//Sub继承Base
var objBase = new Base();//创建对象
objBase.showName();//调用方法
objBase.sayHello();
console.log(objBase);//输出对象
var objSub = new Sub();//新建方法
objSub.showName();//调用原型方法
console.log(objSub);

 

结果:

 

 

注意:Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承。

同时,在原型中定义的属性不会被console.log 作 为对象的属性输出。

 

util.inspect

util.inspect(object,[showHidden],[depth],[colors])

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

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

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

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

 

util.isArray(object)

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

 

util.isRegExp(object)

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

 

util.isDate(object)

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

 

util.isError(object)

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

 

Node.js 文件系统

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

var fs = require("fs");

此章节为对文件的操作,类似JAVA的IO包

链接:https://www.runoob.com/nodejs/nodejs-fs.html

 

Node.js GET/POST请求

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

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

本章节我们将为大家介绍 Node.js GET/POST请求。

获取GET请求内容

由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET请求的参数。

获取 URL 的参数

示例:

var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
    res.writeHead(200,{'Content-Type': 'text/plain; charset=utf-8'});//设置编码格式
    // 解析 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=菜鸟教程&url=www.runoob.com

页面显示:

 

获取 POST 请求内容

 

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

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

 

示例:

var http = require('http');
var querystring = require('querystring');
// 定义了一个post变量
var postHTML =
    '<html><head><meta charset="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 = "";
    // 通过reqdata事件监听函数,每当接受到请求体的数据,就累加到post变量中
    req.on('data', function (chunk) {
        body += chunk;
    });
    // end事件触发后,通过querystring.parsepost解析为真正的POST请求格式,
    // 然后向客户端返回。
    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);//设置端口号

 

浏览器访问:http://localhost:3000

 

然后输入信息点击提交

 

 

Node.js 工具模块

在 Node.js 模块库中有很多好用的模块。接下来我们为大家介绍几种常用模块的使用:

序号

模块名 & 描述

1

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

2

Path 模块
提供了处理和转换文件路径的工具。

3

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

4

DNS 模块
用于解析域名。

5

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

 

具体链接:https://www.runoob.com/nodejs/nodejs-utitlity-module.html

 

 

Node.js Web 模块

 

 

使用 Node 创建 Web 服务器

Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块

示例:

var http = require('http');
var fs = require('fs');
var url = 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; charset=utf-8'});
        }else{
            // HTTP 状态码: 200 : OK
            // Content Type: text/plain
            response.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
            // 响应文件内容
            response.write(data.toString());
        }
        //  发送响应数据
        response.end();
    });
}).listen(8080);
// 控制台会输出以下信息
console.log('Server running at http://127.0.0.1:8080/webServer/index.html');

 

然后直接在浏览器输入对应的链接就能访问你的页面

 

 

Node.js Express 框架

教程:https://www.runoob.com/nodejs/nodejs-express-framework.html

 

 

Node.js 连接 MySQL

安装驱动:cnpm install mysql

 

代码示例:

var mysql = require('mysql');
var connection = mysql.createConnection({
    host: 'localhost',//地址
    user: 'root',//帐号
    password: 'root',//秒秒
    port: '3306',//端口
    database: 'test',//数据库
});
connection.connect();//连接
//
// var  sql = 'select * from temp';
// connection.query(sql,function (err, result) {
//     if(err){
//         console.log('[SELECT ERROR] - ',err.message);
//         return;
//     }
//     console.log('--------------------------SELECT----------------------------');
//     console.log(result);
//     console.log('------------------------------------------------------------\n\n');
// });

//添加
// var sql = "insert into temp values(?,?)";
// var data = ['1','张三'];//代替问号的数据
// connection.query(sql, data, function (err, result) {
//     if (err) {
//         console.log('[INSERT ERROR] - ', err.message);
//         return;
//     }
//     console.log('--------------------------INSERT----------------------------');
//     console.log('INSERT ID:',result);
//     console.log('-----------------------------------------------------------------\n\n');
// })

//修改
// var sql="update temp set name=? where id=?";
// var data=['德玛西亚','1'];
// connection.query(sql,data,function (err,result) {
//     if(err){
//         console.log('[UPDATE ERROR] - ',err.message);
//         return;
//     }
//     console.log('--------------------------UPDATE----------------------------');
//     console.log('UPDATE affectedRows',result.affectedRows);
//     console.log('-----------------------------------------------------------------\n\n');
// })

//删除
// var sql="delete from temp where id=?";
// var data=[2];
// connection.query(sql,data,function (err,result) {
//     if(err){
//         console.log('[DELETE ERROR] - ',err.message);
//         return;
//     }
//     console.log('--------------------------UPDATE----------------------------');
//     console.log('DELETE  affectedRows',result.affectedRows);
//     console.log('-----------------------------------------------------------------\n\n');
// })
connection.end();//关闭

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值