跳至主要內容

Node.js

CoderAn大约 7 分钟后端开发Node

Node.js

交互式解释器

下划线变量(_),可以使用下划线获取上一个表达式的运算结果

> var x = 10
> var y = 20
>  x + y
>  var sum = _
>  console.log(sum)
30_

REPL命令

ctrl+c              //退出当前终端
ctrl+c              //退出Node REPL 按下两次 
ctrl+d              //退出Node REPL
.help               //列出使用命令
.break              //退出多行表达式
.clear              //退出多行表达式
.save <filename>      //保存当前的Node REPL会话到指定文件
.load <filename>      //载入当前的Node REPL会话的文件内容

回调函数

Node.js异步编程的直接体现就是回调。 回调函数接收错误对象作为第一个参数。

$ touch input.txt
$ nano input.txt
hello nodejs

阻塞代码实例

var fs = require('fs');
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log('程序执行结束');

输出

hello nodejs
程序执行结束

程序顺序执行,读取文件阻塞

非阻塞代码实例

var fs = require('fs');
fs.readFile('input.txt',function(err,data){
    if(err)return console.log(err);
    console.log(data.toString());
});
console.log('程序执行结束');

输出

程序执行结束
hello nodejs

程序异步执行,文件读取完成后调用回调函数;后面的程序不会被阻塞。


事件

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

//创建连接事件处理程序
var connectHandler = function connected(){
    console.log('连接成功.');
    //触发接收数据事件
    eventEmitter.emit('data_received');
}
//绑定connection事件处理程序
eventEmitter.on('connection',connectHandler);

//绑定接收数据事件
eventEmitter.on('data_received',function(){
    console.log('数据接收成功.')
})

//触发连接事件
eventEmitter.emit('connection');

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

EventEmitter类

实例方法

addListener(event,listener)

为指定事件添加一个监听器到监听器数组的尾部

on(event,listener)

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

once(event,listener)

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

removeListener(event,listener)

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

removeAllListeners([event])

移除所有事件的监听器,如果指定事件,则移除指定事件的所有监听器。

setMaxListeners(n)

设置事件默认(10)允许的最大监听器数量。

listeners(event)

返回指定事件的监听器数组。

emit(event,[arg1],[arg2],[...])

按照参数的顺序执行每个监听器,如果事件又注册监听器返回true,否则返回false。

类方法

listenerCount(emitter,event)

返回指定事件的监听器数量。

实例事件

newListener

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

  • event 字符串,事件名称
  • listener 处理事件函数

removeListener

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

  • event 字符串,事件名称
  • listener 处理事件函数

error事件

EventEmitter类定义了一个特殊的事件error,包含了错误的语意。 当error被触发时,如果没有响应的监听器,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(缓冲区)

在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用 Buffer.from() 接口去创建Buffer对象。

创建Buffer类

Buffer 提供了以下 API 来创建 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 实例

写入缓冲区

buf.write(string[,offset[,length]][,encoding])
返回值:返回实际写入的大小,如果buffer空间不足,则只会写入部分字符。

从缓冲区读取数据

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

返回值:解码缓冲区数据并使用指定的编码返回字符串。

将Buffer转换为JSON对象

buf.toJSON()

返回值:返回JSON对象

缓冲区合并

Buffer.concat(list[,totalLength])
参数:
    - list 用户合并的Buffer对象数组列表
    - totalLength 指定合并后Buffer对象的总长度 

缓冲区比较

buf.compare(otherBuffer);

拷贝缓冲区

buf.copy(targetBuffer[,targetStart[,sourceStart[,sourceEnd]]])
参数:
  - targetBuffer - 要拷贝的 Buffer 对象。
  - targetStart - 数字, 可选, 默认: 0
  - sourceStart - 数字, 可选, 默认: 0
  - sourceEnd - 数字, 可选, 默认: buffer.length

缓冲区裁剪

buf.slice([start[,end])

缓冲区长度

buf.length;

Node.js Stream 流

Stream

四种流类型:

  • Readable - 可读操作。
  • Writable - 可写操作。
  • Duplex - 可读可写操作.
  • Transform - 操作被写入数据,然后读出结果。

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

  • data - 当有数据可读时触发。
  • end - 没有更多的数据可读时触发。
  • error - 在接收和写入过程中发生错误时触发。
  • finish - 所有数据已被写入到底层系统时触发。

从流中读取数据

var fs = require('fs');
var data = '';
var readerStream = fs.createReadStream('input.txt');
readerStream.setEncoding('UTF8');
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('programing is end.');

写入流

var fs = require('fs');
var data = 'hello nodejs,i am stream.';
var writeStream = fs.createWriteStream('output.txt');
writeStream.write(data,'UTF8');
writeStream.end();
writeStream.on('finish',()=>{
        console.log('write finished.');
})
writeStream.on('error',(err)=>{
        console.log(err.stack);
})
console.log('programing end.');

管道(pipe)

实现大文件的复制。

var fs = require('fs');
var readerStream = fs.createReadStream('input.txt');
var writeStream = fs.createWriteStream('output.txt');
//管道操作
readerStream.pipe(writeStream);
console.log('program end.');

链式流

链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作。 接下来我们就是用管道和链式来压缩和解压文件。 压缩文件

var fs = require('fs');
var zlib = require('zlib');
var readerStream = fs.createReadStream('input.txt');
var writeStream = fs.createWriteStream('input.txt.gz');
readerStream.pipe(zlib.createGzip()).pipe(writeStream);
console.log('program end.');

解压文件

var fs = require('fs');
var zlib = require('zlib');
var readerStream = fs.createReadStream('input.txt.gz');
var writeStream = fs.createWriteStream('input1.txt');
readerStream.pipe(zlib.createGunzip()).pipe(writeStream);
console.log('program end.');

Node.js 路由

server.js

var http = require('http');
var url = require('url');
const PORT = 3000;
var start = function(route){
  var onRequest = function(request,response){
  var pathname = url.parse(request.url).pathname;
    route(pathname);
  }
  http.createServer(onRequest).listen(PORT);
  console.log(`Server start http://localhost:${PORT}`);
}
exports.start = start;

router.js

var route = function(pathname){
  console.log(pathname);
}
exports.route = route;

index.js

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

Node.js Express 框架


模块系统

模块系统的加载优先级

模块系统的加载优先级
模块系统的加载优先级

http模块

安装

$ npm install http

使用

// 引入required模块
var http = require("http");
//创建服务器,接收请求与响应请求
http.createServer(function(request,response){
    //发送HTTP头部
    //HTTP状态值:200   :OK
    //内容类型:text/plain
    response.writeHead(200,{'Content-Type':'text/plain'});

    //发送响应数据
    response.end('Hello World\n');
}).listen(8888)

web框架模块express

安装

$ npm install express       //全局安装
//  安装失败
npm err! Error: connect ECONNREFUSED 127.0.0.1:8087
//  解决办法
$ npm config set proxy null
//  卸载模块
$ npm uninstall express
//  更新模块
$ npm update express
//  搜索模块
$ npm search express

使用

var express = require('express');

上次编辑于:
贡献者: 宗安