了解内置模块
node.js的内置模块就是node本身提供的模块,不用下载,直接使用require引入就可以使用这些模块的方法了。而这些模块在浏览器环境中是不能执行的。以下与大家见面的是我们在node中常用的一些模块,如有记录不完善或者想查看更多的,请前往 nodejs.cn/api/ 了解更多。
path模块
path用于处理文件和目录的路径。
__dirname 返回当前文件所在目录的绝对路径
const path = require("path");
console.log(__dirname);
path.join([...paths]) 用于路径的拼接
const path = require("path");
//路径的拼接
console.log(path.join("/node","index.json"));
path.resolve([...paths]) 将路径或路径片段的序列解析为绝对路径
const path = require("path");
console.log(path.resolve("."));
console.log(path.resolve(".."));
console.log(path.resolve("test1","test2/test3"));
//如果没有传入 path 片段,则 path.resolve() 会返回当前工作目录的绝对路径
path.basename(path[, ext]) 返回 path 的最后一部分
const path = require("path");
console.log(path.basename("/user/test/index.html"));
console.log(path.basename("/user/test/index.html",".html"));
fs模块
fs用于文件或文件夹的读写操作,较常用的是以下几种:
fs.mkdir(path[,options],callback) 异步 新建文件夹
//有三个参数,第一个参数是地址,就是你创建的文件夹存放的地址
//第二个参数不是必填的参数, options 参数可以是一个整数,用于指定文件的模式(权限与粘滞位)。 也可以是一个对象,其中 recursive 属性指定是否创建父目录。
//第三个参数是回调函数,参数就是err错误
fs.mkdir('/tmp/test/web', { recursive: true }, (err) => {
if (err) throw err;
});
fs.mkdirSync(path[, options]) 同步 新建文件夹
//同步和异步的区别就不多说了,在写法上就是同步的方法没有回调函数
//同步调用若是出错,都会终止执行,必须用try catch来捕获错误
拿同步新建文件夹举例:
try{
const result = mkdirSync("./test");
}catch(e){
console.log(new Error(e));
}
fs.rmdir(path,callback) 异步 删除文件夹
fs.rmdir("./test",(err)=>{
console.log(err);
})
fs.rmdirSync(path) 同步 删除文件夹
fs.rmdirSync("./test");
fs.readdir(path[,options],callback) 异步 读取文件夹
//读取文件夹的时候,回调函数中会有两个参数,一个是错误,另一个就是读取的文件
//如果 options 是一个字符串,则指定字符编码。 如果 encoding 设为 'buffer',则返回的文件名是 Buffer,可以定义为 utf8。
fs.readdir("./test",(err,files)=>{
console.log(err);
console.log(files); // 文件夹中的文件,以数组的形式存放
})
fs.readdirSync(path[, options]) 同步 读取文件夹
//如果 options 是一个字符串,则指定字符编码。 如果 encoding 设为 'buffer',则返回的文件名是 Buffer,可以定义为 utf8。
const a = fs.readdirSync('./');
console.log(a); // 文件夹中的文件,以数组的形式存放
fs.readFile(path[, options],callback); 异步 读文件
fs.readFile("../test/test.json",(err,data)=>{
if(err){
console.log(err);
}else{
console.log(JSON.parse(data));
}
});
//callback回调函数中有两个参数,一个是err,另一个是data,读取的数据,一般data的格式都要改变,两种方法:
1.可以写成data.toString;
2.可以调用方法的时候多加一个参数,改变数值类型的 fs.readFile(file,"utf8",callback);
fs.readFileSync(path[, options]) 同步 读文件
const data = fs.readFileSync('../test/test.txt','utf8');
fs.writeFile(file, data[, options], callback) 异步 写文件
fs.writeFile('./test/index.json',JSON.stringify(data),(err)=>{
if(err){
console.log(err);
}
});
//如果没有该文件,会先创建该文件,若存在,会覆盖文件内容
fs.writeFileSync(file, data[, options]) 同步 写文件
try{
fs.writeFileSync('./test/index.json',JSON.stringify(data));
}catch(err){
console.log(err);
}
//如果没有该文件,会先创建该文件,若存在,会覆盖文件内容
fs.appendFile(file, data[, options], callback) 异步 不覆盖写文件
fs.appendFile("./file.txt",data,(err)=>{
console.log(err);
});
// 就是writeFile换成了appendFile,就可以不覆盖的写入内容了
fs.appendFileSync(file, data[, options]) 同步 不覆盖写文件
fs.appendFileSync("./file.txt",data);
fs.unlink(path,callback) 异步 删除文件
fs.unlink("./file.txt",(err)=>{
console.log(err);
});
fs.unlinkSync(path) 同步 删除文件
fs.unlink("./file.txt");
url模块
使用传统的 API 解析 URL 字符串
const url = require("url");
const myURL = url.parse('https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash');
console.log(myURL);
/* 打印结果为解析后的URL对象
Url {
protocol: 'https:',
slashes: true,
auth: 'user:pass',
host: 'sub.host.com:8080',
port: '8080',
hostname: 'sub.host.com',
hash: '#hash',
//查询字符串,这里,如果我们想要以对象形式返回,可以让url.parse的第二个参数为true
search: '?query=string',
query: 'query=string',
pathname: '/p/a/t/h',
path: '/p/a/t/h?query=string',
href: 'https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash'
}
*/
使用 WHATWG 的 API 解析 URL 字符串
const {URL} = require("url");
const myURL = new URL('https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash');
console.log(myURL);
/* 打印结果为解析后的URL对象
Url {
protocol: 'https:',
slashes: true,
auth: 'user:pass',
host: 'sub.host.com:8080',
port: '8080',
hostname: 'sub.host.com',
hash: '#hash',
search: '?query=string',
query: 'query=string',
pathname: '/p/a/t/h',
path: '/p/a/t/h?query=string',
href: 'https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash'
}
*/
querystring模块
queryString就是查询字符串,模块提供了一些实用函数,用于解析与格式化 URL 查询字符串
querystring.parse(str[, sep[, eq[, options]]]) 解析URL的查询字符串
- str <string> 要解析的 URL 查询字符串。
- sep <string> 用于在查询字符串中分隔键值对的子字符串。默认值: '&'。
- eq <string> 用于在查询字符串中分隔键和值的子字符串。默认值: '='。
- options <Object>:
decodeURIComponent <Function> 当解码查询字符串中的百分比编码字符时使用的函数。默认 值: querystring.unescape()。
maxKeys <number> 指定要解析的键的最大数量。指定 0 可移除键的计数限制。默认值: 1000。
const qs = require('querystring');
const b = qs.parse("foo=bar&abc=xyz&abc=123");
console.log(b);
//{ foo: 'bar', abc: [ 'xyz', '123' ] }
//默认情况下,会假定查询字符串中的百分比编码字符使用 UTF-8 编码。 如果使用其他的字符编码,则需要指定其他的 decodeURIComponent 选项:
querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null, { decodeURIComponent: gbkDecodeURIComponent });
querystring.stringify(obj[, sep[, eq[, options]]]) 序列化字符串为url查询字符串
- obj <Object> 要序列化为 URL 查询字符串的对象。
- sep <string> 用于在查询字符串中分隔键值对的子字符串。默认值: '&'。
- eq <string> 用于在查询字符串中分隔键和值的子字符串。默认值: '='。
- options:
encodeURIComponent <Function> 当将查询字符串中不安全的 URL 字符转换为百分比编码时使用的函数。默认值: querystring.escape()。
querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// 返回 'foo=bar&baz=qux&baz=quux&corge='
querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// 返回 'foo:bar;baz:qux'
//默认情况下,查询字符串中需要进行百分比编码的字符将会被编码为 UTF-8。 如果需要其他的编码,则需要指定其他的 encodeURIComponent 选项:
querystring.stringify({ w: '中文', foo: 'bar' }, null, null, { encodeURIComponent: gbkEncodeURIComponent });
events模块
EventEmitter
events 模块提供了一个对象: events.EventEmitter
EventEmitter 的核心就是事件触发与事件监听器功能的封装
EventEmitter 的每个事件由一个事件名和若干个参 数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持 若干个事件监听器。当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作 为回调函数参数传递
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
//eventEmitter.on() 用于注册监听器, eventEmitter.emit() 用于触发事件
myEmitter.on('eventName', () => {
console.log('事件被触发了');
});
myEmitter.emit('eventName');
eventEmitter.emit(eventName,callback) callback中this
eventEmitter.emit() 方法可以传任意数量的参数到监听器函数。 当监听器函数被调用时, this 关键词会被指向监听器所绑定的 EventEmitter 实例
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// 打印:
// aa bb MyEmitter {
// domain: null,
// _events: { event: [Function] },
// _eventsCount: 1,
// _maxListeners: undefined } true
});
myEmitter.emit('event', 'aa', 'bb');
也可以使用 ES6 的箭头函数作为监听器。但 this 关键词不会指向 EventEmitter 实例
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// 打印: aa bb {}
});
myEmitter.emit('event', 'aa', 'bb');
eventEmitter.once()
使用 eventEmitter.once() 可以注册最多可调用一次的监听器。 当事件被触发时,监听器会被注销
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// 打印: 1
myEmitter.emit('event');
// 不触发
emitter.removeListener(eventName, listener)
emitter.removeListener(eventName, listener) 从名为 eventName 的事件的监听器数组中移除指定的 listener
const callback = (stream) => {
console.log('已连接');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
emitter.removeAllListeners([eventName])
emitter.removeAllListeners([eventName]) 移除全部的事件侦听
server.removeAllListeners(['connection']);
stream(流)
流(stream)是 Node.js 中处理流式数据的抽象接口
Node.js 中有四种基本的流类型:
Writable - 可写入数据的流(例如 fs.createWriteStream())。 Readable - 可读取数据的流(例如 fs.createReadStream())。 Duplex - 可读又可写的流(例如 net.Socket)。 Transform - 在读写过程中可以修改或转换数据的 Duplex 流(例如 zlib.createDeflate())。 此外,该模块还包括实用函数 stream.pipeline()、stream.finished() 和 stream.Readable.from()。
几乎所有的 Node.js 应用都在某种程度上使用了流。 下面是一个例子,使用流实现了一个 HTTP 服务器:
const http = require('http');
const server = http.createServer((req, res) => {
// req 是一个 http.IncomingMessage 实例,它是可读流。
// res 是一个 http.ServerResponse 实例,它是可写流。
let body = '';
// 接收数据为 utf8 字符串,
// 如果没有设置字符编码,则会接收到 Buffer 对象。
req.setEncoding('utf8');
// 如果添加了监听器,则可读流会触发 'data' 事件。
req.on('data', (chunk) => {
body += chunk;
});
// 'end' 事件表明整个请求体已被接收。
req.on('end', () => {
try {
const data = JSON.parse(body);
// 响应信息给用户。
res.write(typeof data);
res.end();
} catch (er) {
// json 解析失败。
res.statusCode = 400;
return res.end(`错误: ${er.message}`);
}
});
});
server.listen(1337);
fs.createReadStream(path[, options]) 读取文件流
可读流的事件请具体参考 nodejs.cn/api/stream.… 文档
let fs = require("fs");
let times = 0;
let stream = fs.createReadStream('../test.txt', { start: 10, end: 99 }});
stream.on("data", chunk => {
console.log("第"+(times++)+"次读取的块内容:");
});
stream.on("end", () => {
console.log("END");
});
stream.on("error", err => {
console.log(err);
});
fs.createWriteStream(path[, options]) 写入文件流
可写流的事件请具体参考 nodejs.cn/api/stream.… 文档
let fs = require('fs');
let stream = fs.createWriteStream('../test.txt', { encoding: 'utf8' });
stream.write("要写入的文本1");
stream.write("要写入的文本2");
// ...
//二进制
//stream.write(new Buffer("文本3", 'utf8'));
//stream.write(new Buffer("文本4", 'utf8'));
// ...
stream.end(); // 终止写入
readable.pipe(writable[,options]) 把一个Readable流和一个Writeable流串起来
两个流是可以串起来的,比如把一个Readable流和一个Writeable流串起来,此时,数据就会自动从Readable流进入Writeable流,此操作成为pipe
let fs = require('fs');
let rs = fs.createReadStream("A.txt");
let ws = fs.createWriteStream("B.txt");
rs.pipe(ws);
上述代码就可以实现A.txt中的内容写入到B.txt中,默认情况下,当Readable流中的数据读取完毕后,就会触发end事件,然后自动关闭Writeable流,我们可以通过以下设定来取消自动关闭Writeable流
rs.pipe(ws, { end: false });
http模块
发起http请求
http.request(options[, callback]) / http.request(url[, options][, callback])
url 可以是字符串或 URL 对象。 如果 url 是一个字符串,则会自动使用 [url.URL()] 解析它。 如果它是一个 URL 对象,则会自动转换为普通的 options 对象。
如果同时指定了 url 和 options,则对象会被合并,其中 options 属性优先。
可选的 callback 参数会作为单次监听器被添加到 'response' 事件。
官方事例:
const postData = querystring.stringify({
'msg': '你好世界'
});
const options = {
hostname: 'nodejs.cn',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = http.request(options, (res) => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应头: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`响应主体: ${chunk}`);
});
res.on('end', () => {
console.log('响应中已无数据');
});
});
req.on('error', (e) => {
console.error(`请求遇到问题: ${e.message}`);
});
// 将数据写入请求主体。
req.write(postData);
req.end();
在示例中调用了 req.end()。 使用 http.request() 时,必须始终调用 req.end() 来表示请求的结束,即使没有数据被写入请求主体
http.get(options[, callback]) / http.get(url[, options][, callback])
http
.get(options, response => {
response.setEncoding('utf8');
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
console.log("ok");
});
})
.on("error", (err) => {
console.log("TopicList Request Error: " + err.message);
});
options 接受与 http.request() 相同的 options,但是 method 始终被设置为 GET。 从原型继承的属性会被忽略
使用http模块搭建服务器 http.createServer([options][, requestListener])
Node.js的http模块,已经帮助我们隐藏了处理TCP连接的具体细节,使得我们可以在更高的层次上直接处理,主要是使用http模块提供的request和response对象
request对象封装了http请求 response对象封装了http相应
1、创建一个http服务器(假设文件在server.js):
const http = require('http');
const server = http.createServer((request, response) => {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end("This is a server by Node.js");
});
server.listen(1234);
这样子我们就完成了一个http服务器的创建了,使用node server.js开启,然后只要访问http://localhost:1234,就会看到页面上输出:This is a server by Node.js
2、我们可以看到http.createServer中有两个参数request和response,这两个参数,request是用来获得客户端发送的HTTP请求的(request对象中包含了许多的请求信息),而response是用来让服务器做出回应的
process
process.nextTick(callback[, ...args])
关于process.nextTick后面我们会着重去讲解
crypto模块
crypto 模块提供了加密功能,包括对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装
这块内容,也会单独写一篇文章来深度分析一下
util实用工具
具体内容请参考 nodejs.cn/api/util.ht…
以上这些都是平时在使用node过程中比较常用的一些内容,当然如果说的不全,也希望各位多多包涵,没写全的内容请各位看官到官网去深度挖掘和吸收哦,谢谢~