1. 事件驱动
概念
node核心API构建用的是异步事件驱动架构 其中某些类型的对象又称触发器(emitter) 会触发命名事件来调用函数,又称监听器
所有能触发的事件对象都是EventEmitter类的实例 EventEmitter里存储在events模块中 他是一个核心模块 不需要我们下载 也不需要
我们定义 直接引入使用就可以 他是NodeJS安装的时候自带的 这些对象有一个 eventEmitter.on(函数)用于一个或这个多事件绑定到
命名事件中 events模块 只提供了一个对象 events.EventEmitter 核心就是监听与触发
参数使用
在事件中传递了参数 EvnentEmitter每个事件有一个事件名和若干个参数组成 事件名是一个字符串 表达一定的意思 见名之意 对于每
一个事件 EventEmitter又支持若干个监听器 当事件触发时 注册到这个事件监听器依次被调用 事件参数作为回调参数使用
// 首先引入模块 使用require引入模块
// 引入模块之后 返回的是一个对象
// events是核心模块 不需要下载 也不需要定义 直接在安装JS的时候就已经定义好了 直接使用就可以
const events = require('events');
// console.log(events)
// 我们在使用events的时候 注意 他只有一个实例 实例是EventEmitter
// 我们需要实例化这个实例
let EventEmitter = events.EventEmitter;
// 实例化这个对象
let event = new EventEmitter();
// console.log(event);
// 我们使用实力话的对象event进行绑定和触发事件
// 绑定事件 我们使用on方法 内置两个参数
// 第一个参数是事件的名字 第二个参数是回调函数 回调函数是自定义函数
event.on('I_LOVE_YOU',name=>{
console.log(name + "终于等到你");
});
// 触发事件 我们使用events对象中的emit方法
// 内置若干参数 第一个参数是触发的事件的名字 第二个开始的参数是事件的参数
event.emit('I_LOVE_YOU','Mary');
event.emit('I_LOVE_YOU','Eric');
event.emit('I_LOVE_YOU','Eric');
event.emit('I_LOVE_YOU','Eric');
event.emit('I_LOVE_YOU','Eric');
2. 模块(重点)
核心模块
核心模块就是NodeJS安装的时候自带的模块 也可以叫做内置模块 但是学名 核心模块
常用的核心模块有
enevts : 事件模块
fs : 文件模块
url模块 path模块 http模块 querystring模块
第三方模块
第三模块是需要下载的 我们一般情况下很多时候 都会使用第三方模块 比如说NodeJS最好的框架 express
express其实就是一个第三方模块
为什么要有第三方模块
Node自身体积很小 所以说自身功能不多 我们很多时候 很多功能基本上都是有第三方模块完成的
第三放模块其实就是我们封装好的JS文件 上传到了官方
模块的名字是全球唯一的 不用担心命名冲突问题
第三方模块管理工具是npm工具
在包管理工具中 我们引入了commonJS规范 CommonJS包规范是理论,NPM是其中一种实践。
对于Node而言,NPM帮助其完成了第三方模块的发布、安装和依赖等
借助NPM,Node与第三方模块之间形成了很好的一个生态系统
npm指令
npm init 初始化项目(创建package.json)
下载包之前一定要先初始化 否则下载不了
初始化之后 生成package.json文件 这是初始化文件
npm i/install 包名 安装指定的包 默认安装下载最新版本
npm i/install 包名 安装指定的包 @版本号,不加版本默认为最新
npm i/install 包名 --save 安装指定的包并添加项目依赖
npm i/install 包名 --save-dev 安装指定的包并添加开发依赖
npm i/install 包名 -g 全局安装(一般都是一些工具)
npm uninstall 卸载包
npm s/search 包名 搜索包
npm r/remove 包名 删除一个包
自定义模块
自定义模块其实就是我们自己定义的JS文件 我们也是通过require进行引入的 但是 我们模块中还是需要暴露
暴露使用的是exports 可以单体引入 也可以集中引入
在Node中 我们引入自定义模块的时候 一定要加上路径 即使是当前目录 那么也不能省略./
使用
暴露 : exports 或者 module.exports
暴露有三种方式可以暴露 但是暴露的结果是一样的
引入 : require 引入
module.exports 和 export之间的区别
他们的堆栈空间都是一样的 所以说使用起来 没什么区别 都是暴露成员
但是 如果说我们使用module.exports暴露一个对象的话 那么我们会覆盖exports暴露的成员
暴露
// 第一种方式暴露
// exports.username = 'admin';
// exports.password = '123';
// exports.obj = {
// name : 'Eric',
// age : 18,
// sex : '男'
// }
// exports.fun = ()=>{
// console.log('你好 我是函数');
// }
// 第二种暴露方式
// module.exports.username = 'admin';
// module.exports.password = '123';
// module.exports.obj = {
// // username,
// // password,
// name : 'Eric',
// age : 18,
// sex : '男'
// }
// module.exports.fun = ()=>{
// console.log('你好 我是函数');
// }
// 第三种暴露方式
exports.username = 'admin';
module.exports.password = '123';
let obj = {
name : 'Eric',
age : 18,
sex : '男'
}
let fun = ()=>{
console.log('你好 我是函数');
}
module.exports = {
obj,
fun
}
引入
// 引入模块
// 引入自定义模块不需要加后缀名 加了也没错
const public = require('./4.public');
// 引入的public是一个对象
// 对象中的成员都是我们暴露的内容
console.log(public);
// console.log(public.username);
// console.log(public.password);
// console.log(public.obj);
// public.fun();
// console.log(module.exports === exports);
// console.log(typeof exports);
3. Buffer
概念
Buffer 结构和数组非常像 操作的方式也相似 数组中不能存储二进制的文件 而buffer专门存储二进制的数据
文件流的写入 网络请求数据处理 javascript 语言不能读取或操作数据流机制
buffer在全局作用域 不用引入 直接使用 buffer中存储的是二进制的数据 显示的时候 是以16进制显示
buffer中每个元素从00-ff 0-255 buffer 中的每个元素 占用内存的一个字节 8比特 buffer是对底层内存的直接操作
8bt == 1B
1024B == 1KB
1204KB == 1MB
1024MB == 1GB
1024GB == 1TB
1024TB == 1PB
方法
Buffer.from(str) 将一个字符串转换成buffer
buf.toString(); 将缓冲区的数据 转成字符串
Buffer的转换
// 使用Buffer
// let str = 'offcn';
let str = 'offcn优就业';
// console.log(str);
// 将字符串转化为buffer
// 使用buffer.from方法 内置一个参数 参数是字符串
let buf = Buffer.from(str);
console.log(buf);
// 一个汉字占用3个字节
console.log(buf.length);
// 将Buffer转化为字符串 使用toString();
console.log(buf.toString());
// 将数组转化为Buffer
let arr = [];
arr.push(buf);
console.log(arr);
// console.log(arr.toString());
// 将Buffer从数组中取出 使用Buffer.concat方法
let c = Buffer.concat(arr);
console.log(c);
console.log(c.toString());
Buffer和base64之间的转化
将Buffer转化为base64格式的字符串 就是一个转解码的加密串
let obj = {
username : 'Eric',
password : '123'
};
// 使用buffer将obj对象转化为base64格式 目的是让别人认不出来
// 1、将obj对象转化为字符串
let json = JSON.stringify(obj);
// 2、将JSON转化为buffer
let buf = Buffer.from(json);
// 3、将buffer转化为base64格式的字符串
let str = buf.toString('base64');
console.log(str);
// 将base64格式的字符串转化为对象
// let str = 'eyJ1c2VybmFtZSI6IkVyaWMiLCJwYXNzd29yZCI6IjEyMyJ9';
// 1、将base格式的字符串转化为Buffer
// 内置两个参数 第一个参数是字符串
// 第二个参数是你将什么格式的字符串转化为buffer 那么第二个参数就是什么
let base64Buf = Buffer.from(str,'base64');
// console.log(base64Buf);
// 将buffer转化为字符串
let result = base64Buf.toString();
// console.log(result);
// 将JSON转化为对象
let oldObj = JSON.parse(result);
console.log(oldObj);
4. 文件操作
文件操作指的是NodeJS对文件和目录的操作
主要指的是文件读取和文件的写入 文件的读取指的是度取出文件的内容 文件的写入指的是将数据写入得到文件中
一般情况下 文件操作分为两部分 第一部分指的是文件的数据操作 就是将数据写入文件和读取出来
第二部分是文件的结构操作 指的是删除文件 删除目录 读取目录 创建目录
文件操作使用的是我们NodeJS中的核心模块fs 不需要下载 直接使用
在我们的fs模块中 我们使用的fs中的所有方法 传递回调函数的都是异步方法
但是每一个异步方法 都对应着一个同步方法 同步方法和异步方法唯一的不同是 没有传递回调函数
同步方法有返回值 同步方法的名字在异步方法名字后面加上Sync
文件数据操作
读取文件 : readFile方法
内置三个参数
第一个参数是文件的路径+文件名
第二个参数是字符集 可选
第三个参数是回调函数
回调内置两个参数 第一个参数是错误 第二个参数是返回的数据
返回的数据 如果说我们传递readFile中的第二个参数 那么返回的是读取的数据结果
如果说我们没有传递readFile的第二个参数 那么我们返回的是Buffer
使用
const fs = require('fs');
// console.log(fs);
// 使用readFile方法
// fs.readFile('./file/test.txt','utf-8',(error,data)=>{
// if (error){
// console.log(error);
// }else{
// console.log(data);
// }
// })
// 传递两个参数的时候 第二个参数省略 data是一个Buffer
fs.readFile('./file/test.txt',(error,data)=>{
if (error){
console.log(error);
}else{
console.log(data);
console.log(data.length);
}
})
读取文件 : readFileSync
内置两个参数 除了回调参数不传 其他一样
返回值是读取的数据或者是buffer
使用
// 同步方法
// let result = fs.readFileSync('./file/test.txt','utf-8');
let result = fs.readFileSync('./file/1.jpg');
console.log(result);
文件的写入
将数据写入到文件中 首先 我们文件写入分为三部分
1.打开文件
2.写入文件
3.关闭文件
文件写入分为四种写入方式
1.同步写入 — 最直观
openSync : 打开文件
如果是写入操作 打开文件的时候 如果文件不存在 那么文件自动创建
内置三个参数
第一个参数是打开文件的路径 + 文件名
第二个参数是打开文件的方式
r : 只读
w : 写入 覆盖写
a : 写入 追加写
第三个参数是打开文件的权限 但是这个参数几乎不传
返回值是资源句柄 打开文件的资源
writeSync : 写入数据
内置四个参数
第一个参数是资源
第二个参数是写入的内容
第三个参数是字符集
第四个参数是写入的起始位置 但是一般不传
closeSync : 关闭文件
内置一个参数 参数是资源
2.异步写入
需要三个方法
open : 打开文件
内置四个参数
第一个参数是打开文件的路径 + 文件名
第二个参数是打开文件的方式
r : 只读
w : 写入 覆盖写
a : 写入 追加写
第三个参数是打开文件的权限 但是这个参数几乎不传 可选
第四个参数是回调函数
回调内置两个参数
第一个参数是错误
第二个参数是资源句柄
write : 写入文件
内置五个参数
第一个参数是资源
第二个参数是写入的内容
第三个参数是字符集
第四个参数是写入的起始位置 但是一般不传 可选
第五个参数是回调函数
回调内置一个参数 参数是错误
close : 关闭文件
内置两个参数
第一个参数是资源
第二个参数是回调函数
回调内置一个参数 参数是错误
3.简单写入
只需要一个方法 方法是writeFile
内置四个参数
第一个参数是文件的路径 + 文件名
第二个参数是写入的数据
第三个参数是描述 是一个对象 对象中有两个属性
一个属性是 : 写入的方式
另二个属性是 : 写入的字符集
第四个参数是回调函数
回调内置一个参数 参数是错误
同步方法writeFileSync 少一个参数 多一个返回值undefined