node和express框架
node中自带的包
- events事件发射器
- http 创建一个服务
- global对象 默认this是空对象与global不同 __filename __dirname
- process对象 常用 process.cwd() process.env process.stdout.write(data): 将数据写入标准输出流(通常是控制台)。process.stderr.write(data): 将数据写入标准错误流
- path 提供了对路径的处理方法
- Buffer alloc创建Buffer对象 from将类似数组转换成Buffer toString 类数组读取
- file fs中的readFile、writeFile、appendFile、copyFile、watchFile open close fs.stat() fs.rmdir()删除文件 用promisify()函数将其处理成async风格
- stream pipe方法实现流之间的数据传输
rs.pipe(ws)
,从可读流中读写数据传入到可写流中 Readable Writable 监听不同的事件来处理流的各种状态和行为 文件流
事件执行机制
-
同步任务执行阶段(Synchronous Execution):首先执行主线程上的同步任务,包括执行 JavaScript 代码、执行 DOM 操作等。
-
微任务执行阶段(Microtask Execution):在同步任务执行完毕后,会立即执行所有微任务。微任务包括 Promise 的 then() 方法注册的回调函数、MutationObserver 的回调函数等。
-
宏任务执行阶段(Macrotask Execution):在执行完所有微任务后,会选择执行宏任务。常见的宏任务包括 setTimeout、setInterval、setImmediate(Node.js 环境)、requestAnimationFrame(浏览器环境)、I/O 操作、UI 渲染等。在宏任务执行期间,可能会有新的微任务产生,它们会被添加到微任务队列中,在宏任务执行完毕后立即执行,每执行一个宏任务之后立刻检查微任务队列。
-
更新渲染阶段(Render):如果环境支持并且需要更新渲染,则执行与渲染相关的任务。在浏览器环境中,这涉及到重绘和回流操作,通常会在宏任务执行后立即进行
通信
通信必要条件
1.主机之间需要有传输介质,协商网络速率,主机上要有网卡设备
2.通讯方式有交换机和路由器通讯,通过Mac地址来唯一标识一台主机,交换机建立多台主机互联如图:交换机接口有上限,局域网存在大量主机会造成广播风暴
3.OSI七层模型
物理层:定义物理介质的传输方式,以传输原始比特流,各种物理设备和标准例如USB设备。
数据链路层:在直接连接的节点之间提供可靠的数据传输,确定目标主机。协议:PPP(点对点协议,数据帧封装)。
网络层:处理数据包的路由和转发,确定目标网络。协议:IP(定义数据包格式和地址结构)、ARP(IP地址解析成MAC地址)。
传输层:提供端到端的数据传输服务,确保数据的可靠性和完整性。协议:TCP(可靠端到端服务,保证数据顺序可靠完整)、UDP(无连接数据传输,实时性
会话层:控制网络连接建立与终止
表示层:负责数据的格式化、编码和加密解密。协议:TLS/SSL(提供了数据加密和身份验证的安全传输层协议)、ASCII(字符编码)、JPEG(图像压缩,网络上传输存储图像)。
应用层:用户与网络的接口。协议:HTTP(超文本传输协议,实现万维网上信息传递)、FTP(网络上传输文件协议)、SMTP(邮件服务器传输电子邮件)、DNS(域名解析成IP地址)
4.数据封装和解封装
封装是应用层往下(发送端),解封装是物理层往上(接收端)
5.TCP协议的三次握手和四次挥手
连接过程采用三次握手建立连接
客户端向服务器发送 SYN 报文:客户端发送一个 SYN(同步)报文段,表示请求建立连接,并选择一个初始的序列号;服务器响应 SYN 报文:服务器收到 SYN 报文后,会回复一个 SYN/ACK 报文,表示收到请求,并确认客户端的请求,同时也选择一个初始的序列号;客户端确认 SYN/ACK 报文:客户端收到 SYN/ACK 报文后,会发送一个 ACK 报文作为对服务器的响应,表示连接建立成功。
四次挥手连接释放
发送方发送 FIN 报文:当发送方的数据发送完毕后,会发送一个 FIN 报文,表示数据发送结束。
接收方确认 FIN 报文:接收方收到 FIN 报文后,会发送一个 ACK 报文作为对 FIN 报文的确认。
接收方发送 FIN 报文:接收方也会发送一个 FIN 报文给发送方,表示它也没有数据要发送了。
发送方确认 FIN 报文:发送方收到接收方的 FIN 报文后,会发送一个 ACK 报文作为对 FIN 报文的确认,然后关闭连接。
TCP数据
net模块TCP通信的创建
新建client.js充当客户端,用node启动命令启动,新建server.js充当服务端,命令启动
//server.js
const net = require('net')
// 创建服务端实例
const server = net.createServer()
const PORT = 1234
const HOST = 'localhost'
server.listen(PORT, HOST)
server.on('listening', () => {
console.log(`服务端已经开启在 ${HOST}: ${PORT}`)
})
// 接收消息 回写消息
server.on('connection', (socket) => {
//双工流,既可写又可读
socket.on('data', (chunk) => {
const msg = chunk.toString()
console.log(msg)
// 回数据
socket.write(Buffer.from('您好' + msg))
})
})
server.on('close', () => {
console.log('服务端关闭了')
})
server.on('error', (err) => {
if (err.code == 'EADDRINUSE') {
console.log('地址正在被使用')
}else{
console.log(err)
}
})
const net = require('net')
const client = net.createConnection({
port: 1234,
host: '127.0.0.1'
})
client.on('connect', () => {
client.write('拉勾教育')
})
client.on('data', (chunk) => {
console.log(chunk.toString())
})
client.on('error', (err) => {
console.log(err)
})
client.on('close', () => {
console.log('客户端断开连接')
})
TCP数据粘包是发送端的多个数据包被分割或合并成一个或多个数据包的现象
解决办法发送端的时间间隔延长,在客户端
let dataArr = [
'拉勾教育2',
'拉勾教育3',
'拉勾教育4',
'拉勾教育5',
]
client.on('connect', () => {
client.write('拉勾教育1')
for(let i=0; i<dataArr.length; i++) {
(function (val, index) {
setTimeout(() => {
client.write(val)
}, 1000 * (index +1))
})(dataArr[i], i)
}
})
或者接收端缓冲数据之后再消费
还有一种办法就是数据封包拆包来解决粘包问题 TODO:
ContentType类型
application/json: JSON 格式的数据
application/x-www-form-urlencoded: 表单数据编码格式,编码为username=john_doe&password=P%40ssw0rd%21
multipart/form-data: 多部分表单数据编码格式,用于上传文件和其他二进制数据。
客户端代理
就是让客户端的js文件首先能够访问服务器端js通信,接着将客户端也变成服务端监听其他端口成为本地服务端,浏览器就可以通过输入本地服务端的端口号访问到外部服务端发送的数据
静态服务工具命令行工具
lgserve开始工作准备
1.新建目录结构如下
2.在www.js中添加如下代码,上面注释意思是在node环境下执行
3.修改package.json中的bin中东西
4.npm link之后直接在命令行输入lgserve命令
5.commander包的使用
6.
npm publish即可发布包,事先看是否登录 npm login
npm发布一个库
"build": "vue-cli-service build --mode pre146":这个脚本定义了一个名为 build 的命令,用于执行项目的构建任务。它使用了 Vue CLI Service 的 build 命令,并传递了一个 --mode 参数,值为 pre146,用于指定构建的模式。
"lib": "vue-cli-service build --target lib -name chengquim --dest lib src/plugins/index.js":这个脚本定义了一个名为 lib 的命令,用于构建一个库。它也使用了 Vue CLI Service 的 build 命令,并传递了一系列参数,包括 --target lib(指定构建目标为库)、-name chengquim(指定库的名称为 chengquim)、--dest lib(指定构建输出目录为 lib)、以及入口文件路径 src/plugins/index.js。
"push": "pnpm lib && npm version patch && npm publish":这个脚本定义了一个名为 push 的命令,用于执行一系列操作,包括构建库、升级版本、以及发布到 npm。它首先执行 pnpm lib 命令,用于构建库(可能是一个笔误,应该是 npm lib),然后执行 npm version patch 命令,用于升级版本号,并最后执行 npm publish 命令,用于将包发布到 npm registry。
express的使用
1.错误处理中间件和404页面的配置
// 在所有的中间件之后挂载错误处理中间件
app.use((err, req, res, next) => {
console.log('错误', err)
res.status(500).json({
error: err.message
})
})
// 通常会在所有的路由之后配置处理 404 的内容
// 请求进来从上到下依次匹配
app.use((req, res, next) => {
res.status(404).send('404 Not Found.')
})
然后在每个路由请求中加入try catch,在catch中添加
// 如果将任何内容传递给next() 函数(字符串'route'除外),Express都会将当前请求视为错误,并且将跳过所有剩余的无错误处理路由和中间件函数。
// next() 往后匹配下一个中间件
// next('route') 往后匹配当前中间件堆栈中的下一个
next(err) // 跳过所有剩余的无错误处理路由和中间件函数。
2.给路由限定访问前缀
const express = require('express')
// 1. 创建路由实例
// 路由实例其实就相当于一个 mini Express 实例
在路由实例上配置路由
const router = express.Router()
app.use('/todos', router)
3.morgan 是一个Node.js中常用的HTTP请求日志记录中间件
4.使用模板引擎渲染页面
.art模板
app.engine('html', require('express-art-template')) // 当渲染以 .art 结尾的资源文件的时候使用 express-art-template
app.set('view options', { // art-template 模板引擎配置
debug: process.env.NODE_ENV !== 'production'
})
app.set('views', path.join(__dirname, 'views')) // 模板文件的存储目录
app.set('view engine', 'html') // 可以省略的模板文件后缀名
app.get('/',(res,req)=>{
// 只要配置模板引擎,就可以使用 res.render 方法渲染页面了
// 1、读模板文件 2、渲染 3、发送响应
res.render('index', {
foo: 'bar',
todos
})
})
5.托管静态资源可以加上访问前缀,可以托管多个资源目录
6.express中返回数据的方式res.send() res.status(200).json() res.render() res.sendFile() res.downLoad()
7.定义中间件函数授权路由匹配是否可访问,挂载数据在req上后面的都可以访问到
const auth = require('../middleware/auth')
// 创建文章
router.post('/', auth, articleValidator.createArticle, articleCtrl.createArticle)
8.使用express-validator来验证客户端向服务器传输的数据是否符合规范,通过中间件函数定义不同的数据验证方法让每一个路由有自己的验证规则
9.express-session用于处理会话管理,允许在客户端和服务器之间存储会话数据,会话持久化到内存数据库或文件系统,提供对会话数据的加密和签名功能,确保会话数据的安全和完整性
express和vue结合
在HTML文件script标签中引用Vue进行数据绑定,响应事件,然后配置模板引擎,能用res.render将html文件响应给服务端,请求页面的路由查询数据库,用模板引擎将查询到的数据和html页面绑定在一起,通过res.render发送给客户端,调用接口的路由从.json数据库获取到数据以后通过res.json()等发送给服务端,不管是请求页面还是调用接口,都应该在服务器中配置路由,实现相关功能。
express TODO:小型express的实现
mongoose
1.mongoose的Schema中特殊字段的处理
const userSchema = new mongoose.Schema({
password: {
type: String,
required: true,
set: value => md5(value),
select: false
},
})
2.moogose中定义Schema表连接
author: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
}
3.在Mongoose中,populate()方法和exec()方法通常一起使用,用于填充关联数据并执行查询。find findOne create updateOne updateMany deleteOne deleteMany