
3.6 Node.js常用核心模块
学习Node.js必须掌握其核心模块,就像学习JavaScript必须掌握函数、对象、数据类型、DOM、BOM等知识一样。
Node.js的核心模块很多,这里介绍几个比较常用的:events、fs、stream、http模块。
3.6.1 events模块
事件驱动、非阻塞IO是Node.js的特点,所以事件模块是非常重要的模块。Node.js绝大多数模块都继承了events。
基于事件的编程是典型的发布-订阅模式的实现,有效地解耦了发布者和订阅者,发布者只需要关心事件的触发,不需要关心触发之后的逻辑,而订阅者只关注订阅,不需要关注事件是由谁来触发。
1.基本使用
使用事件模块有以下几个步骤:
(1)实例化事件监听器实例。
(2)注册事件。
(3)触发事件。
const EventEmitter = require('events'); // 实例化事件监听器 const emitter = new EventEmitter(); // 注册事件 emitter.on('click', function (param1) { console.log('触发了点击', param1); }); // 触发事件 emitter.emit('click', 'demo'); // 再次触发 emitter.emit('click', 'demo');
以上例程输出如下:
触发了点击 demo 触发了点击 demo
2.一次性监听
Node.js中可以对同一个事件进行多次监听,也可以多次触发同一事件。如果需要在事件触发监听函数一次之后不再继续触发,可以调用once()来进行一次性监听。
const EventEmitter = require('events'); const emitter = new EventEmitter(); emitter.once('click', function (param1) { console.log('触发了点击', param1); }); emitter.emit('click', 'demo'); emitter.emit('click', 'demo');
以上例程输出如下:
触发了点击demo
调用once函数监听的事件不管触发了多少次事件,都只会执行一次回调函数。
3.6.2 fs模块
fs是File System的缩写,也就是Node.js用来操作系统文件的模块。
1.读取文件
调用fs.readFile()函数即可读取文件,函数签名如下:
fs.readFile(path[, options], callback)
· path:文件路径。
· options:选项。
· callback:回调函数。

2.写入文件
调用fs.writeFile()可以写入文件,函数签名如下:
fs.writeFile(path, content[, options], callback)
· path:文件路径。
· content:文件内容。
· options:选项。
· callback:回调函数。

3.追加内容
如果文件存在时不需要覆盖,可以调用fs.appendFile()来追加文件内容,函数签名如下:
fs.appendFile(path, content[, options], callback)
· path:文件路径。
· content:文件内容。
· options:选项。
· callback:回调函数。

4.删除文件
调用fs.unlink()可以删除文件,函数签名如下:
fs.unlink(path, callback)
· path:文件路径。
· callback:回调函数。

本函数不能删除文件夹,需要调用fs.rmdir()才可以删除文件夹。
5.创建文件夹
调用fs.mkdir()可以创建文件夹,函数签名如下:
fs.mkdir(path[, options], callback)
· path:文件夹路径。
· options:选项。
· callback:回调函数。

6.读取文件夹内容
调用fs.readdir()可以读取文件夹内容,函数签名如下:
fs.readdir(path[, options], callback)
· path:文件夹路径。
· options:选项。
· callback:回调函数。

7.删除文件夹
调用fs.rmdir()可以删除文件夹,函数签名如下:
fs.rmdir(path, callback)
· path:文件夹路径。
· callback:回调函数。

3.6.3 stream接口
stream是Node.js的一个抽象接口,很多对象都实现了这个接口。比如请求HTTP接口时的request对象就是一个stream。
stream是EventEmitter的实例。常用的事件有:
· data:当有数据可读时触发。
· end:当没有更多数据可读时触发。
· error:在读取或写入时发生错误时触发。
· finish:在所有数据写入系统底层时触发。
Node.js中stream有4种类型:
· Readable:可读。
· Writable:可写。
· Duplex:可读可写。
· Transform:数据转换。
1.读取流
读取流都可以通过监听data和end事件来接收数据。比如文件读取流、HTTP请求读取流都可以用这个方法来读取,不需要关心读取流的类型。
通过流的方式读取文件有个很大的优点:内存占用低,可以以小块的形式处理数据。而直接调用fs.readFile()之类的函数,如果文件过大,可能会撑爆内存。

2.写入流
通过调用写入流的write()方法来写入数据,调用写入流的end()来完成写入。当数据写入完毕时会触发finish事件。

3.管道流
管道提供了一个读取流到写入流的机制。我们通常用管道从一个流中获取数据并将数据传递到另外一个流中。多个管道可以串行处理,数据会依次流经每个管道。
实际上在上面的写入流示例中,已经体现了管道流的思想。只不过通过调用读取流的pipe()方法可以简化该步骤。

4.数据转换流
数据转换流本质还是利用管道进行处理,将读取流通过pipe()操作传入转换流,以达到数据转换的目的。
比如我们需要将一个文本文件通过gzip压缩后保存到磁盘,可以使用下面的代码。

3.6.4 http模块
http模块主要用于创建HTTP服务器处理请求、创建HTTP客户端发出请求。
1.http客户端
http客户端可以向指定的URL发出请求,回调一个读取流,可以通过操作读取流进行数据输出或者保存等操作。
下面以保存笔者博客所在的头像文件为例:

2.http服务器
http服务可以说是Node.js最为常见的一种服务类型,本节中只简单做个示例。在实际开发中,很少直接使用Node.js内置的http模块进行开发,一般都是使用Web框架。
const http = require('http'); // 导入HTTP模块 // 创建HTTP服务器,req为请求对象,resp为响应对象 const server = http.createServer((req, resp) => { resp.end(JSON.stringify(req.headers)); }); server.listen(8080, () => console.log('listen on 8080')); // 监听端口
执行该JS之后会监听本机8080端口,通过浏览器访问可以得到如图3-1所示的输出。

图3-1