Nodejs
node概述
特点
单线程所以可以快速I/O操作.
用途
- 开发桌面应用程序
- 开发服务器应用程序
全局对象
setTimeout
setInterval
注意这两者在浏览器中返回的是==数字==,但是在node中返回的是==对象==
setImmediate
: 类似于setTimeout(()=>{},0)
console
__dirname
: 当前文件的目录,注意,该属性并不是global
里面的属性__filename
: 获取当前文件的路径,该属性并不是global
里面的属性Buffer
: 类型化数组,继承自UInt8Array
process
:cwd()
: 输出当前终端(命令行)所在目录exit()
: 强制退出当前node进程,可以传入一个退出状态码,默认为0
,表示没有错误.argv
: 获取执行命令时的所有命令行参数platform
: 获取当前的操作系统kill(pid)
: 杀死进程env
: 获取环境变量
node的模块化细节
模块的查找
- 绝对路径: 直接导入
- 相对路径:
./
或../
转换为绝对路径后导入. - 相对路径
- 检查是否是内置模块: 如
fs
,path
等. - 检查当前目录中的
node_modules
- 检查上级目录中的
node_modules
- 转换为绝对路径
- 加载模块
- 检查是否是内置模块: 如
- 关于后缀名
- 如果不提供后缀名,则node会尝试补全
js
,json
,node
,mjs
- 关于文件名
- 如果仅提供目录,不提供文件名,则自动寻找该目录中的
index.js
package.json
中的main
字段- 表示包的默认入口
- 导入或执行包时若只提供目录,则使用main补全入口
- 默认值为
index.js
- 如果仅提供目录,不提供文件名,则自动寻找该目录中的
module对象
记录了当前模块的信息
require函数
当执行一个模块或使用require时,会将模块放置在一个函数环境中
1 | function require(modulePath) { |
[扩展] Node中的ES模块化
基本内置模块
OS
EOL
: end of linearch()
: CPU架构cpus()
: CPU信息fremem()
:空闲内存homedir()
: 用户目录hostname()
: 主机名tmpdir()
: 操作系统的临时目录
path
basename
: 获取文件名(路径中的最后一部分)sep
: 路径分割符(Linux和Mac/
,windows\
)delimiter
: 多个路径之间的分割符(Linux和Mac:
, Windows;
)dirname
: 获取路径(除去文件名)extname
: 获取扩展名join
: 把多段路径按照目前操作系统的规则拼接为一个完整的目录normalrize
: 得到规范化路径relative
: 得到左边想要找右边的相对路径(右边相对于左边的相对路径)resolve
: 解析为完整路径
url
util
callbackify
: 把Promise转换为回调函数的形式promisify
: 把回调函数转换为Promise的形式inherits
: 继承isDeepStrictEqual
: 对象是否严格相等.
文件I/O
fs模块
readFile
: 读取一个文件
1 | const fs = require('fs') |
writeFile
: 写文件stat
: 文件或目录的信息size
: 占用的字节数atime
: 上次访问时间mtime
: 上次文件内容被修改的时间ctime
: 上次文件状态被修改的时间birthtime
: 文件创建时间isDirectory()
: 判断是否是目录isFile()
: 判断是否是文件
readdir
: 获取目录中的文件和子目录mkdir
: 创建目录exists
:判断文件或目录是否存在
文件流
什么是流
流是指数据的流动,数据从一个地方缓缓地流动到另一个地方
流是有方向的
- 可读流(readable): 数据从源头流向内存
- 可写流(writable): 数据从内存流向源头
- 双工流: 数据既可以从源头流向内存,也可以从内存流向源头.
为什么需要流
其他介质和内存的数据规模不一致
其他介质和内存的数据处理能力不一致
文件流
什么是文件流
内存数据和磁盘文件数据之间的流动
文件流的创建
fs.createReadStream(path[, options])
- 含义: 创建一个文件可读流,用于读取文件的内容
- path: 读取的文件路径
- options: 可选配置
- encoding: 编码方式
- start: 起始字节
- end: 结束字节
- highWaterMark: 每次读取数量
- 如果encoding有值,该数量表示一个字符数
- 如果encoding为null,该数量表示字节数
- 返回: Readable的子类ReadStream
- 事件: rs.on(事件名, 处理函数)
- open: 文件打开事件,文件打开后触发
- error: 出错时触发
- close: 文件关闭事件,文件关闭后触发
- data
- 读取到一部分数据后触发
- 注册
data
事件后,才会真正开始读取 - 每次读取
hightWaterMark
指定的数量 - 回调函数中会附带读取到的数据
- end
- 事件: rs.pause(): 暂停读取
- 事件: rs.resume(): 恢复读取
- 事件: rs.on(事件名, 处理函数)
fs.createWriteStream(path[,options])
- 含义:创建一个文件可写流,用于写入文件内容
- path: 写入的文件路径
- options: 可选配置
- flags: 操作文件的方式
- encoding: 编码方式
- start: 起始字节
- highWaterMark: 每次最多写入的字节数,与
encoding
无关
- 返回: Writable的子类WriteStream
- ws.write(data)
- 写入一组数据
- data可以是字符串或
Buffer
- 返回一个
boolean
值- true: 写入通道没有被填满,接下来的数据可以直接写入,无需排队
- false: 写入通道目前已经被填满,接下来的数据将进入写入队列
- 当写入队列清空时,会触发
drain
事件.
- ws.end([data])
- ws.write(data)
fs.pipe(ws)
net模块
回顾http请求
普通模式
非持久http连接,每次请求都需要重新进行三次握手,四次挥手
长连接模式
持久http请求.
net模块能干什么
net
是一个通信模块
利用它,可以实现
- 进程间的通信 IPC
- 网络通信 TCP/IP
创建客户端
1 | const net = require('net'); |
返回一个socket
文件
socket
是一个特殊的文件- 在node中表现为一个双工流对象
- 通过向流写入内容发送数据
- 通过监听流的内容获取数据.
创建服务器
http模块
建立在net模块之上
http.request(url[, options][,callback])
http.createServer([options][,requestListener])
我是客户端
- 请求:
ClientRequeset
对象 - 响应:
IncomingMessage
对象
我是服务器
- 请求:
IncomingMessage
对象 - 响应:
ServerResponse
对象
https模块
node生命周期

timers
: 存放计时器的回调函数
poll
: 轮询队列,除了timers
和checks
,绝大部分都会进入,比如:文件读取,监听用户请求
- 运作方式
- 如果poll中有回调,依次执行回调,直到清空队列
- 如果poll中没有回调
- 等待其他队列中出现回调,结束该阶段,进入下一阶段
- 如果其他队列也没有回调,持续等待,直到出现回调为止.
1 | const start = Date.now(); |
check
: 检查阶段,使用setImmediate()
的回调
1 | let i = 0; |
1 | let i = 0; |
1 | setTimeout(() => { |
1 | const fs = require('fs'); |
事件循环中,每次打算执行一个回调之前,必须要先清空nextTick
和Promise
队列
1 | setImmediate(() => { |
1 | async function async1() { |
EventEmitter
node事件管理的通用机制
1 | const { EventEmitter } = require('events'); |
mysql的驱动程序
什么是驱动程序
驱动程序是连接内存和其他存储介质的桥梁
mysql驱动程序是连接内存数据和mysql数据的桥梁
mysql驱动程序通常使用
- mysql
- mysql2
mysql2的使用
Sequelize简介
ORM
ORM(Object Relation Mapping)
,对象关系映射.
通过ORM框架,可以自动的把程序中的对象和数据库关联.
ORM框架会隐藏具体的数据库底层细节,让开发者使用同样的数据操作接口,完成对不同数据库的操作.
ORM的优势
- 开发者不用关心数据库,仅需关心对象
- 可轻易的完成数据库的移植
- 无须拼接复杂的sql语句即可完成精确查询.

Node中的ORM
Sequelize
比较成熟
- JS
- TS
TypeORM
不够成熟
模型定义和同步
模型的增删改
三层架构

模拟数据
使用Mock.js
数据抓取
涉及到的库
- axios
- cheerio
数据查询
- 查询单个数据:
findOne
- 按照主键查询单个数据:
findByPk
- 查询多个数据:
findAll
- 查询数量:
count
- 包含关系:
include
MD5加密
MD5
是hash
加密算法的一种,可以将任何一个字符串,加密成一个固定长度的字符串.
单向加密,无法破解.
momentjs(现在更常用dayjs)
概念
utc和北京时间
utc: 世界协调时,以英国格林威治时间为标准
北京时间为 utc + 8h
时间戳
某个utc时间到utc1970-1-1的0:00
的毫秒数,也可以是秒数,用小数部分记录毫秒.
注意: 时间戳表示的是utc时间的差异.
utc时间
对服务器的影响
服务器可能会部署到世界的任何位置
服务器内部应该统一使用utc
时间或时间戳,包括数据库.
对客户端的影响
- 客户端要给不同地区的客户友好的显示时间.
- 客户端应该把时间戳转换为本地时间显示

数据验证
数据验证的位置
- 前端(客户端): 为了用户体验
- 路由层: 验证接口格式是否正常
- 业务逻辑层: 保证业务完整性
- 数据库验证(约束): 保证数据完整性
相关库
- validator: 用于验证某个字符串是否满足某个规则
- validate: 用于验证某个对象是否满足某个规则
访问器和虚拟字段
1 | get() |
日志记录
log4js