《新时期的Node.js入门》 | |||
---|---|---|---|
作者 | 李锴 | 出版社 | 清华大学出版社 |
ISBN | 9787302487807 | 出版时间 | 2018.1 |
豆瓣网址 | https://book.douban.com/subject/30170564/ | 是否有电子版 | 微信读书 |
阅读日期 | 2020-6-25 | 更新日期 | |
相关链接 | 备注 | github |
如果你想读这本书,使用微信扫码即可:
全书结构如下:
本书的第二章深入浅出解释了一下常用的内置模块,可供简单了解。
常用模块
Module
还是 CommonJS AMD ES 三种模块方案。
CommonJS
Node早于es模块发布之前,所以选用了CommonJS,特点是同步加载代码,不适合web中使用。
每个文件是一个模块,必须通过 exports require 导入导出
// export
var person={}
module.exports = person
// require
var persion = require('./xx')
为什么cjs里的require是同步?这里有一个重复引入的概念:第一次引入之后会留在缓存中,后续使用会直接使用缓存。一个可能是公共依赖的模块,尽可能要一步到位加载完成。缓存的好处很多,足以抵过以外重启带来的性能损失。
缓存是依赖路径的。
引入未知的模块要保持警惕,如果一个模块中使用了定时器、循环、连接数据库等,可能会导致内存泄露。
node模块中的this指向什么: module.exports
,这个后面再补充。模块作用域:
(function(exports,require,module,__filename,__dirname){
})()
Buffer
- buffer 是node的数据类型,用来处理二进制数据
- 前端es6+增加了ArrayBuffer用来操作二进制数据
一般fs读写,网络操作,默认返回的Buffer
var buffer = new Buffer([0x48])
var buffer = new Buffer('hello')
console.log(buffer)
// 注意这种写法已经被弃用,后面统一使用 Buffer.from
var buffer = Buffer.from([0x48])
var buffer = Buffer.from('hello')
buffer.toString('utf-8',0,5) // 默认就是utf-8
当我们用buffer去读一个汉字,会发现一个汉字占用三个字节。注意这里的3,后面要考。
Buffer 的一个常见处理场景,是处理http的post请求,比如下载一个文件
var body = ''
req.setEncoding('uft8')
req.on('data',chunk=>body+=chunk)
req.on('end',()=>{})
这里的 body += chunk
实际上是 body+=chunk.toString()
,如果是英文没关系,如果有中文,这里默认是 utf-8 可能会乱码。
highWaterMark
最高水平线,表示内部缓存区最多容纳的字节数,超出的就会停止读取文件,默认64k
如果一个100k的文件,默认读取,会分成 64+36触发两次data事件,然后触发end事件。如果hightWaterMark 设置过小,会多次调用,影响性能。
刚才一个汉字utf-8占用三个字节,如果 highWaterMark
=10`,会除不开,打印时候就会有乱码。
上面的 +=
写法已经过时,现在要求使用 Push
var data=[]
req.on('data',chunk=>data.push(chunk))
req.on('end',()=>{
var buf = Buffer.concat(data)
// log buf.toString()
})
放入数组,后面再转换
FS
很多api
readFile
适合体积较小的文件,如果文件尺寸大,建议使用 stream。
fs.writeFile 写文件
fs.stat
fs.stat文件状态,建议先先判断是否存在stat,再open或者read或者write
有一个 fs.fstat
,和stat的区别是,fstat的第一个参数是文件描述符,通常搭配open使用
其他略
http
也简单过 http.createServer
定义了 connection
request
事件
res对象
// setHeader 单个设置
responese.setHeader('Content-Type','application/json')
// 多个header使用 writeHead
tcp
Socket是对tcp协议的一种封装方式。忽略
什么是https SSL
ssl是独立的,和http结合是https,和webSocket是wss
ssl和tls差异很小,一般不需要做区分
localhost利用OpenSSL 这里忽略
WebSocket
使用过 socket.io封装库
Stream
var stream = require('stream')
四种基础stream类型:
- readable 可读流 fs.createReadStream()
- writable 可写流 fs.createWriteStream()
- duplex 可读可写 net.Socket
- transform 操作写入的数据,读取结果,用于输入和输出不要求匹配的场景
主要是前两种
var stream = require('stream')
var fs = require('fs')
var readStream = fs.createReadStream('./a.txt','utf-8')
readStream.on('data',data=>console.log(data))
readStream.on('close',()=>{})
readStream.on('error',()=>{})
在 writeable stream 中有 drain 事件
如果我们有一个读写流,通过pipe给可写流,如果读写速度快,会等待可写,在内存中缓存,大小也是有HigtWaterMark 限制的。超出缓存,读写会暂停,等到缓存区清空,触发 drain
多进程服务
单线程线程崩溃会导致程序退出,也无法充分利用多核cpu,提供了 child_process
模块来实现多进程的支持。
child_process:
- exec
- spawn 最基础,其他多多少少借助这个api
- fork
- execFile
为了统一node创建多进程的服务方式,后续新增了 cluster 模块,可以看做封装了 child_process
cluster.fork cluster.isMaster 是主从模式