node基础,快速入门node.js(4)

135 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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)

  • eventName string|事件的名称。
  • 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)

  • eventName string|事件的名称。
  • 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])

  • eventName string|符号
  • ...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到数据后通过回调函数的方式返回给前端

image-20220802223542534.png

现在有了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模块