携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
events模块
events模块是node的核心模块,几乎所有常用的node模块都继承了events模块,比如http、fs等。
EventEmitter
多数 Node.js 核心 API 都是采用惯用的异步事件驱动架构,其中某些类型的对象(称为触发器)会周期性地触发命名事件来调用函数对象(监听器)。例如,一个net.Server对象会在每次有新连接时触发一个事件;一个 fs.ReadStream 会在文件被打开时触发一个事件;一个 stream会在数据可读时触发事件。所有发出事件的对象都是EventEmitter该类的实例。
示例:eventEmitter.on()方法用于注册监听器,eventEmitter.emit()方法用于触发事件。
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
eventEmitter.on(eventName, listener)
eventNamestring|事件的名称。listener回调函数- 返回:EventEmitter
事件可以被多次触发
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2
emitter.once(eventName, listener)
eventNamestring|事件的名称。listener回调函数- 返回:EventEmitter
注册一个最多调用一次的侦听器。一旦事件被发出,监听器就会被注销然后被调用。
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored
emitter.emit(eventName[, ...args])
eventNamestring|符号...args任何- 返回:布尔值
按监听器的注册顺序,同步地调用每个注册到名为eventName事件的监听器,并传入提供的参数。如果事件有监听器,则返回true,否则返回false。
var EventEmitter = require('events');
var emitter = new EventEmitter();
emitter.on('test1',function(){});
console.log(emitter.emit('test1'));//true
console.log(emitter.emit('test2'));//false
events模块解决回调函数
之前http模块补充中模拟get请求的时候,是在get到数据后通过回调函数的方式返回给前端
现在有了events模块,就可以在发起请求前注册监听器,请求完成后触发事件,将数据传回前端。
const EventEmitter = require('events'); //导入events模块
class MyEmitter extends EventEmitter {} //继承EventEmitter类
let myEmitter = null; //myEmitter对象赋初始值为空
const http = require('http');
const https = require('https');
const url = require('url');
const server = http.createServer((req, res) => {
res.writeHead(200, {
"Content-Type": "application/json;charset=utf-8",
"access-control-allow-origin": "*" //解决跨域问题
});
let urlobj = url.parse(req.url, true);
switch (urlobj.pathname) {
case '/api/aa':
//作为客户端 去猫眼要数据
myEmitter = new MyEmitter(); //创建myEmitter对象
myEmitter.on('event', (data) => { //给myEmitter对象挂载event事件,注册监听器
res.end(data);
})
httpGet();
break;
default:
res.end('404 Not Found');
}
}).listen(8080, () => {
console.log('http://localhost:8080');
})
function httpGet() {
let data = "";
https.get(`https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E6%88%90%E9%83%BD&ci=59&channelId=4`, (res) => {
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
myEmitter.emit('event',data); //触发event事件,把data传给监听事件的回调函数
});
})
}
fs模块
fs模块能够以标准 POSIX 函数为模型的方式与文件系统进行交互。所有fs模块的API操作都具有同步、回调和基于Promise的形式,并且可以使用 CommonJS 语法和 ES6 模块 (ESM) 访问。
fs.mkdir
const fs = require('fs');
/**
* @description: 新建目录
* @param {*} bbb 目录名
* @param {*} err 错误信息
* @return {*}
*/
fs.mkdir("./bbb", (err) => {
if (err && err.code === "EEXIST") {
console.log("目录已经存在!");
}else{
console.log("目录创建成功!")
}
})
fs.rename
const fs = require('fs');
let dirName = "bbb";
let reDirName = "public";
/**
* @description: 目录重命名
* @param {*} param1 原目录名
* @param {*} param2 新目录名
* @param {*} err 报错信息
* @return {*}
*/
fs.rename(`./${dirName}`, `./${reDirName}`, (err) => {
if (err && err.code === "EPERM") {
console.log(`已有名为${reDirName}的目录!`);
} else if (err && err.code === "ENOENT") {
console.log(`没有名为${dirName}的目录!`);
}
})
fs.rmdir
//当目录中还有子目录或者文件时会报错
const fs = require('fs');
let dirName = "public";
/**
* @description: 删除目录
* @param {*} param1 删除的目录名
* @param {*} err 报错信息
* @return {*}
*/
fs.rmdir(`./${dirName}`, (err) => {
if (err && err.code === "ENOENT") {
console.log(`没有名为${dirName}的目录!`);
}
})
fs.writeFile
const fs = require('fs');
/**
* @description: 写入文件
* @param {*} public 文件路径,没有会自动创建
* @param {*} hello 写入内容
* @param {*} err 报错信息
* @return {*}
*/
fs.writeFile("./public/a.txt", "hello world", (err) => {
console.log(err);
})
fs.appendFile
const fs = require('fs');
/**
* @description: 追加文件内容
* @param {*} public 文件路径
* @param {*} n 追加内容
* @param {*} err 报错信息
* @return {*}
*/
fs.appendFile("./public/a.txt", "\n你好", (err) => {
console.log(err);
})
fs.readFile
const fs = require('fs');
/**
* @description: 读取文件内容
* @param {*} public 文件路径
* @param {*} utf8 编码格式
* @param {*} err 报错信息
* @param {*} data 返回数据
* @return {*}
*/
fs.readFile("./public/a.txt", "utf8", (err, data) => {
if(err) throw err;
console.log(data);
})
fs.unlink
const fs = require('fs');
/**
* @description: 删除文件
* @param {*} public 文件路径
* @param {*} err 报错信息
* @return {*}
*/
fs.unlink("./public/a.txt", err => {
if (err && err.code === "ENOENT") {
console.log(`该文件不存在!`);
}
})
fs.readdir
const fs = require('fs');
/**
* @description: 读取目录
* @param {*} public
* @param {*} err
* @param {*} data
* @return {*}
*/
fs.readdir("./public", (err, data) => {
if(!err){
console.log(data);
}
})
fs.stat
const fs = require('fs');
/**
* @description: 路径下的文件信息
* @param {*} public 路径
* @param {*} err 报错信息
* @param {*} data 文件信息
* @return {*}
*/
fs.stat("./public/b.html", (err, data) => {
if(!err){
console.log(data.isFile());
console.log(data.isDirectory());
}
})
递归删除目录
const fs = require('fs');
let folder = "./public"
/**
* @description: 根据目录递归删除文件和子目录
* @param {*} folder 目录路径
* @return {*}
*/
function deldir(folder) {
let flag = fs.statSync(folder);
if (!flag.isDirectory()) {
throw new Error("Directory " + folder + " is not a directory.");
}
let dirArr = fs.readdirSync(folder);
dirArr.forEach(item => {
let sub_path = `${folder}/${item}`;
let sub_type = fs.statSync(sub_path);
if (sub_type.isFile()) {
fs.unlinkSync(sub_path);
} else if (sub_type.isDirectory()) {
deldir(sub_path)
}
})
fs.rmdirSync(folder);
}
deldir(folder);
小结
fs的promise就略了,同步代码自行测试,fs模块