Node.js 基本内置模块
Node.js 提供了许多内置模块,这些模块可以帮助开发者快速实现各种功能。
注意:想用到这些内置模块里的功能是需要先用const 变量名 = require(‘模块名’); 引入模块
1.fs (File System)模块
作用:用于处理文件系统操作,如读取、写入、删除文件或读取、写入、删除文件夹等。
(1)读取文件内容
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
//err参数表示报错参数
//data参数表示读取这个文件里面的数据
(2)写入文件
//异步写入
fs.writeFile('example.txt', 'Hello World!', (err) => {
if (err) throw err;
console.log('File has been written!');
});
//err参数表示报错参数
//同步写入
try{
fs.writeFileSync('./fileForWrite1.txt', 'hello world', 'utf8');
console.log('文件写入成功');
}catch(err){
throw err;
}
(3)删除文件
//异步
fs.unlink('example.txt', (err) => {
if (err) throw err;
console.log('File has been deleted!');
});
//err参数表示报错参数
//同步
fs.unlinkSync('./fileForUnlink.txt');
(4)创建目录
//异步版本(如果目录已存在,会报错)
var fs = require('fs');
fs.mkdir('./hello', function(err){
if(err) throw err;
console.log('目录创建成功');
});
//同步版本
fs.mkdirSync('./hello');
(5)文件重命名
//异步
// fs.rename(oldPath, newPath, callback)
var fs = require('fs');
fs.rename('./hello', './world', function(err){
if(err) throw err;
console.log('重命名成功');
});
//同步
var fs = require('fs');
fs.renameSync('./world', './hello');
2.path模块
作用:用于处理文件和目录路径。
在nodejs中,path是个使用频率很高,但却让人又爱又恨的模块。部分因为文档说的不够清晰,部分因为接口的平台差异性。
(1)获取所在路径
var path = require('path');
var filepath = '/tmp/demo/js/test.js';
// 输出:/tmp/demo/js
console.log( path.dirname(filepath) );
(2)获取文件名
严格意义上来说,path.basename(filepath) 只是输出路径的最后一部分,并不会判断是否文件名。
但大部分时候,我们可以用它来作为简易的“获取文件名“的方法。
var path = require('path');
// 输出:test.js
console.log( path.basename('/tmp/demo/js/test.js') );
// 输出:test
console.log( path.basename('/tmp/demo/js/test/') );
// 输出:test
console.log( path.basename('/tmp/demo/js/test') );
(3)获取文件扩展名
var path = require('path');
var filepath = '/tmp/demo/js/test.js';
// 输出:.js
console.log( path.extname(filepath) );
path.extname('index.html')
// returns '.html'
path.extname('index.coffee.md')
// returns '.md'
path.extname('index.')
// returns '.'
path.extname('index')
// returns ''
path.extname('.index')
// returns ''
3.http模块----内容较多后续会专门讲解
作用:用于创建 HTTP 服务器和客户端。
大多数nodejs开发者都是冲着开发web server的目的选择了nodejs。正如官网所展示的,借助http模块,可以几行代码就搞定一个超迷你的web server。
在nodejs中,http可以说是最核心的模块,同时也是比较复杂的一个模块。上手很简单,但一旦深入学习,不少初学者就会觉得头疼,不知从何入手。
本文先从一个简单的例子出发,引出http模块最核心的四个实例。看完本文,应该就能够对http模块有个整体的认识。
在下面的例子中,我们创建了1个web服务器、1个http客户端:
服务器server:接收来自客户端的请求,并将客户端请求的地址返回给客户端。
客户端client:向服务器发起请求,并将服务器返回的内容打印到控制台。
var http = require('http');
// http server 例子
var server = http.createServer(function(serverReq, serverRes){
var url = serverReq.url;
serverRes.end( '您访问的地址是:' + url );
});
server.listen(3000);
// http client 例子
var client = http.get('http://127.0.0.1:3000', function(clientRes){
clientRes.pipe(process.stdout);
});
代码解释:
在上面这个简单的例子里,涉及了4个实例。大部分时候,serverReq、serverRes 才是主角。
server:http.Server实例,用来提供服务,处理客户端的请求。
client:http.ClientReques实例,用来向服务端发起请求。
serverReq/clientRes:其实都是 http.IncomingMessage实。serverReq 用来获取客户端请求的相关信息,如request header;而clientRes用来获取服务端返回的相关信息,比如response header。
serverRes:http.ServerResponse实例
4.events模块
作用:用于处理事件驱动编程。
events模块是node的核心模块之一,几乎所有常用的node模块都继承了events模块,比如http、fs等
例子1:单个事件监听器
var EventEmitter = require('events');
//创建一个名为 Man 的新类,它扩展了 EventEmitter 类
class Man extends EventEmitter {}
// 创建 Man 类的新实例
var man = new Man();
man.on('wakeup', function(){
console.log('man has woken up');
});
man.emit('wakeup');
// 输出如下:
// man has woken up
例子2:同个事件,多个事件监听器
var EventEmitter = require('events');
//创建一个名为 Man 的新类,它扩展了 EventEmitter 类
class Man extends EventEmitter {}
var man = new Man();
man.on('wakeup', function(){
console.log('man has woken up');
});
man.on('wakeup', function(){
console.log('man has woken up again');
});
man.emit('wakeup');
// 输出如下:
// man has woken up
// man has woken up again
例子3:只运行一次的事件监听器
var EventEmitter = require('events');
//创建一个名为 Man 的新类,它扩展了 EventEmitter 类
class Man extends EventEmitter {}
var man = new Man();
man.on('wakeup', function(){
console.log('man has woken up');
});
man.once('wakeup', function(){
console.log('man has woken up again');
});
man.emit('wakeup');
man.emit('wakeup');
// 输出如下:
// man has woken up
// man has woken up again
// man has woken up
例子4:注册事件监听器前,事件先触发
var EventEmitter = require('events');
//创建一个名为 Man 的新类,它扩展了 EventEmitter 类
class Man extends EventEmitter {}
var man = new Man();
man.emit('wakeup', 1);
man.on('wakeup', function(index){
console.log('man has woken up ->' + index);
});
man.emit('wakeup', 2);
// 输出如下:
// man has woken up ->2
例子5:异步执行,还是顺序执行
var EventEmitter = require('events');
//创建一个名为 Man 的新类,它扩展了 EventEmitter 类
class Man extends EventEmitter {}
var man = new Man();
man.on('wakeup', function(){
console.log('man has woken up'); // 代码1
});
man.emit('wakeup');
console.log('woman has woken up'); // 代码2
// 输出如下:
// man has woken up
// woman has woken up
例子6:移除事件监听器
var EventEmitter = require('events');
function wakeup(){
console.log('man has woken up');
}
//创建一个名为 Man 的新类,它扩展了 EventEmitter 类
class Man extends EventEmitter {}
var man = new Man();
man.on('wakeup', wakeup);
man.emit('wakeup');
man.removeListener('wakeup', wakeup);
man.emit('wakeup');
// 输出如下:
// man has woken up
5.os模块—不经常使用
作用:用于获取操作系统相关信息。
const os = require('os');
// 获取操作系统平台
console.log(os.platform()); // 输出: darwin(MacOS)、win32(Windows)或linux(Linux)
// 获取总内存量(以字节为单位)
console.log(os.totalmem()); // 输出: 17179869184(示例值)
6.url模块
作用:用于解析和格式化 URL
nodejs中,提供了url这个非常实用的模块,用来做URL的解析。在做node服务端的开发时会经常用到。使用很简单,总共只有3个方法
url模块三个方法分别是:
1.parse(urlString):将url字符串,解析成object,便于开发者进行操作。
2.format(urlObj):.parse() 方法的反向操作。
3.resove(from, to):以from作为起始地址,解析出完整的目标地址(还是看直接看例子好些
(1)url解析:url.parse()
完整语法:url.parse(urlString[, parseQueryString[, slashesDenoteHost]])
var url = require('url');
var str = 'http://Chyingp:HelloWorld@ke.qq.com:8080/index.html?nick=%E7%A8%8B%E5%BA%8F%E7%8C%BF%E5%B0%8F%E5%8D%A1#part=1';
var obj = url.parse(str);
console.log(obj);
输出如下:
Url {
protocol: 'http:',
slashes: true,
auth: 'Chyingp:HelloWorld',
host: 'ke.qq.com:8080',
port: '8080',
hostname: 'ke.qq.com',
hash: '#part=1',
search: '?nick=%E7%A8%8B%E5%BA%8F%E7%8C%BF%E5%B0%8F%E5%8D%A1',
query: 'nick=%E7%A8%8B%E5%BA%8F%E7%8C%BF%E5%B0%8F%E5%8D%A1',
pathname: '/index.html',
path: '/index.html?nick=%E7%A8%8B%E5%BA%8F%E7%8C%BF%E5%B0%8F%E5%8D%A1',
href: 'http://Chyingp:HelloWorld@ke.qq.com:8080/index.html?nick=%E7%A8%8B%E5%BA%8F%E7%8C%BF%E5%B0%8F%E5%8D%A1#part=1' }
对输出解释:
protocol:协议,需要注意的是包含了:,并且是小写的。
slashes:如果:后面跟了两个//,那么为true。
auth:认证信息,如果有密码,为usrname:passwd,如果没有,则为usrname。注意,这里区分大小写。
host:主机名。注意包含了端口,比如ke.qq.com:8080,并且是小写的。
hostname:主机名,不包含端口,并且是小写的。
hash:哈希部分,注意包含了#。
search:查询字符串,注意,包含了?,此外,值是没有经过decode的。
query:字符串 或者 对象。如果是字符串,则是search去掉?,其余一样;如果是对象,那么是decode过的。
path:路径部分,包含search部分。
pathname:路径部分,不包含search部分。
href:原始的地址。不过需要注意的是,protocol、host会被转成小写字母
(2)url拼接:url.format(urlObject)
url.parse(str)的反向操作,没什么好说的。urlObject包含了很多字段,比如protocol、slashes、protocol等,且不一定需要全部传,所以有一套解析逻辑。
过程比较冗长,大部分时候不需要用到
(3)url.resolve(from, to)
url.resolve('/one/two/three', 'four') // '/one/two/four'
url.resolve('http://example.com/', '/one') // 'http://example.com/one'
url.resolve('http://example.com/one', '/two') // 'http://example.com/two'
7.crypto模块----知识较难
(1)hash例子
hash.digest([encoding]):计算摘要。encoding可以是hex、latin1或者base64。如果声明了encoding,那么返回字符串。否则,返回Buffer实例。
注意:调用hash.digest()后,hash对象就作废了,再次调用就会出错。
hash.update(data[, input_encoding]):input_encoding可以是utf8、ascii或者latin1。如果data是字符串,且没有指定 input_encoding,则默认是utf8。
注意:hash.update()方法可以调用多次。
var crypto = require('crypto');
var fs = require('fs');
var content = fs.readFileSync('./test.txt', {encoding: 'utf8'});
var hash = crypto.createHash('sha256');
var output;
hash.update(content);
output = hash.digest('hex');
console.log(output);
// 输出内容为:
// b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
(2)HMAC例子
HMAC的全称是Hash-based Message Authentication Code,也即在hash的加盐运算。
算法细节可以参考附录链接,具体到使用的话,跟hash模块差不多,选定hash算法,指定“盐”即可。
var crypto = require('crypto');
var fs = require('fs');
var secret = 'secret';
var hmac = crypto.createHmac('sha256', secret);
var input = fs.readFileSync('./test.txt', {encoding: 'utf8'});
hmac.update(input);
console.log( hmac.digest('hex') );
// 输出:
// 734cc62f32841568f45715aeb9f4d7891324e6d948e4c6c60c0621cdac48623a
(3)加密/解密
加解密主要用到下面两组方法:
加密:
crypto.createCipher(algorithm, password)
crypto.createCipheriv(algorithm, key, iv)
解密:
crypto.createDecipher(algorithm, password)
crypto.createDecipheriv(algorithm, key, iv)
crypto.createCipher(algorithm, password)
algorithm:加密算法,比如aes192,具体有哪些可选的算法,依赖于本地openssl的版本,可以通过openssl list-cipher-algorithms命令查看支持哪些算法。
password:用来生成密钥(key)、初始化向量(IV)。
var crypto = require('crypto');
var secret = 'secret';
var cipher = crypto.createCipher('aes192', secret);
var content = 'hello';
var cryptedContent;
cipher.update(content);
cryptedContent = cipher.final('hex');
console.log(cryptedContent);
// 输出:
// 71d30ec9bc926b5dbbd5150bf9d3e5fb
crypto.createCipheriv(algorithm, key, iv)
相对于 crypto.createCipher() 来说,crypto.createCipheriv() 需要提供key和iv,而 crypto.createCipher() 是根据用户提供的 password 算出来的。
key、iv 可以是Buffer,也可以是utf8编码的字符串,这里需要关注的是它们的长度:
key:根据选择的算法有关,比如 aes128、aes192、aes256,长度分别是128、192、256位(16、24、32字节)
iv:都是128位(16字节)
var crypto = require('crypto');
var key = crypto.randomBytes(192/8);
var iv = crypto.randomBytes(128/8);
var algorithm = 'aes192';
function encrypt(text){
var cipher = crypto.createCipheriv(algorithm, key, iv);
cipher.update(text);
return cipher.final('hex');
}
function decrypt(encrypted){
var decipher = crypto.createDecipheriv(algorithm, key, iv);
decipher.update(encrypted, 'hex');
return decipher.final('utf8');
}
var content = 'hello';
var crypted = encrypt('hello');
console.log( crypted );
var decrypted = decrypt( crypted );
console.log( decrypted ); // 输出:utf8
8.querystring模块
在nodejs中,提供了querystring这个模块,用来做url查询参数的解析,使用非常简单。
模块总共有四个方法,绝大部分时,我们只会用到 .parse()、 .stringify() 两个方法。剩余的方法,感兴趣的同学可自行查看文档。
.parse():对url查询参数(字符串)进行解析,生成易于分析的json格式。
.stringif():跟**.parse()**相反,用于拼接查询查询。
(1)查询参数解析:querystring.parse()
参数:querystring.parse(str[, sep[, eq[, options]]])
第四个参数几乎不会用到,直接不讨论. 第二个, 第三个其实也很少用到,但某些时候还是可以用一下。直接看例子
var querystring = require('querystring');
var str = 'nick=casper&age=24';
var obj = querystring.parse(str);
console.log(JSON.stringify(obj, null, 4));
输出如下:
{
"nick": "casper",
"age": "24"
}
再来看下两个参数:sep、eq有什么作用。相当于可以替换&、=为自定义字符,对于下面的场景来说还是挺省事的。
var str1 = 'nick=casper&age=24&extra=name-chyingp|country-cn';
var obj1 = querystring.parse(str1);
var obj2 = querystring.parse(obj1.extra, '|', '-');
console.log(JSON.stringify(obj2, null, 4));
输出如下:
{
"name": "chyingp",
"country": "cn"
}
(2)查询参数拼接:querystring.stringify()
语法:querystring.stringify(obj[, sep[, eq[, options]]])
相当于parse的逆向操作。直接看代码
var querystring = require('querystring');
var obj1 = {
"nick": "casper",
"age": "24"
};
var str1 = querystring.stringify(obj1);
console.log(str1);
var obj2 = {
"name": "chyingp",
"country": "cn"
};
var str2 = querystring.stringify(obj2, '|', '-');
console.log(str2);
输出如下:
nick=casper&age=24
name-chyingp|country-cn