目录
Node特点:
- 事件驱动
- 异步非阻塞
- 轻量且高效
因为node的io的效率更高,所以把原本后台所做的视图模板部分交给node去做。
模块化
Node.js采用commonjs规范,将代码进行拆分,每个文件就是独立的代码块。文件路径就是模块名。
在编写模块时,有require、exports、module三个变量可供使用。
Require:引入模块。
Require()的作用:
-
执行导入的模块中的代码
-
返回导入模块中的接口对象
Exports:导出当前模块的公共方法或属性,别的模块通过require就可以得到当前模块的exports对象。
一般顺序是,模块进行导出后,其它模块就可以引入这个模块了。
Module.exports:用来导出一个默认对象,不指定对象名,常用于关于修改模块的原始导出对象,比如原本模块导出的是一个对象,可以将它修改为导出一个函数。
注意:虽然一般情况下export=module.exports,但系统在找内存地址的时候,找的是modules.exports,所以当更改exports的内存指向时,与module.exports无关,此时模块还module.exports的值,也就是原始值,除非对module.exports进行修改,才会改变。
Exports只能设置单个属性,但module.exports可以单个设置属性,也可以重新整个赋值。
原因:在node中,导出以module.exports为准,因为exports是module.exports的引用,真正起作用的还是module.exports
模块初始化:一个模块的js代码仅在模块第一次使用时才被执行一次,并在使用过程中进行初始化,之后缓存起来以便后续继续使用。
加载第三方包:使用npm将第三方包下载后,使用require进行引入。
使用require加载第三方包的机制: 1. 优先在加载该包的模块的同级目录node_modules中查找第三方包,找到它之后再在此第三方包的名下找到它的package.json中的main属性,此属性的值表示此模块加载的时候加载哪个文件。
如果package.json中没有main属性,则默认加载第三方包中的index.js文件。
如果没有node_modules则向上一级查找,如果找到根目录都没有,则会报错:can not found module xxx。
文件
在对文件进行操作时,使用异步的方式最佳,然后使用promise和async/await来避免回调地狱的出现。
文件读取
- 导入文件模块
let fs=require('fs')
Node不仅可以进行同步读写,也能进行异步读写,他有同步和异步两种接口
1.1 同步(缺点:等待或阻塞)
打开:
fs.openSync(path,flag,mode)
var fd=fs.openSync('hello.txt','r')//第三个参数一般使用默认值即可,可以不用填
读取:
var content=fs.readFileSync('hello.txt',{flag:'r',encoding:"utf-8"})
console.log(content)
flag表示的是读写方式,encoding表示编码格式,要注意编码形式。
1.2 异步
读取:
var content=fs.readFile('hello.txt',{flag:'r',encoding:"utf-8"},function(err,data){
if(err){
//错误信息
}else{
console.log(data)
}
})
console.log(456)
文件写入
- 导入fs模块
let fs=require('fs')
2. 异步写入
function writefs(path,content){
return new promise(function(resolve,reject){
fs.writeFile('test.txt',"晚饭",{flag:"w",encoding:"utf-8"},function(err){//w表示覆盖写入,a表示追加写入
if(err){
reject(err)
}else{
resolve("成功")
}
})
})
}
async function writeList(){
await writefs('1c.txt',"今天吃什么?");
await writefs('1c.txt',"今天吃烧烤");
await writefs('1c.txt',"今天吃烤鸭");
}
writeList()
文件删除
let fs=require('fs')
fs.unlink(Path,callback)
Buffer(缓存数据)
使用buffer的原因:
- 数组不能进行二进制数据的操作
- Js数组没有固定的大小内存,存取速度慢,效率低
- 提升数组性能
在内存空间开辟出固定大小的内存,空间上是连续的,效率比较高
- 将字符串变为buffer对象
var str ="helloworld" let buf=Buffer.from(str)
- 将buffer对象转为字符串
let strs=buf.toString(buf)
- 开辟一个空的buffer(缓存区)
let buf1=Buffer.alloc(10)//10个字节 let buf2=Buffer.allocUnsafe(10)
alloc在新开辟时会先进行清空再开辟,里面不会有遗留的东西。
allocUnsafe在新开辟时就直接开辟了,里面如果有遗留也不会管,但这样做速度更快效率更高,通常使用它来获取之前遗留下来的东西
读取/删除目录
- 读取
fs.readdir(path,callback)
- 删除
fs.readdir(path,callback)
输入输出
- 引入readline模块
var readline=require('readline')
- 实例化接口对象
let r1=readline.createInterface({ output:process.stdout, input:process.stdin })
- 设置question事件(这里的answer就是输入的东西)
r1.question("今晚吃什么",function(answer){ console.log("不知道",answer) r1.close() }) r1.on('close',function(){ process.exit(0) //加上退出,这样才会结束 })
文件流
写入流
在文件的读写当中,有很多时候没办法一次性将需要读写的文件全部读写,所以使用文件流,能够一点一点的读。
let fs=require("fs");
lef
-
创建写入流对象(写入流接口)
fs.creatWriteStream(path,option,callback) let ws=fs.creatWriteStream('heiio.txt',{flags:"w",encoding:"utf-8"})
-
监听文件打开与关闭事件
ws.on('open',function(){ console.log("文件打开") }) ws.on('close',function(){ console.log("文件关闭") })
-
文件流式写入
ws.write("helloworld!",function(err){ if(err){ console.log(err) }else{ console.log("流入完成") } })
-
关闭流
ws.end(function(){ console.log("文件写入完毕") })
读取流
let fs=require("fs");
- 创建读取流
let rs=fs.creatReadStream('heiio.txt',{flags:"r",encoding:"utf-8"})
- 监听文件打开与关闭事件
rs.on('open',function(){ console.log("文件打开") }) rs.on('close',function(){ console.log("文件关闭") })
先流入后流出的整个流程
先流入后流出,即先进行写入后进行读取,例如先读取一个视频,再将这些读取的数据写进新的副本中。
let rs=fs.creatReadStream('heiio.txt',{flags:"r",encoding:"utf-8"})//读取
let ws=fs.creatWriteStream('heiio2.txt',{flags:"w",encoding:"utf-8"})//写入
rs.on('open',function(){
console.log("文件打开")
})
rs.on('close',function(){
ws.end(function(){//当读取完时,也写入完了,所以将end放在此处
console.log("文件写入完毕")
})
console.log("文件关闭")
})
rs.on('data',function(chunk){
console.log(chunk)
console.log("单批数据流入完成,它的大小是"+chunk.length)
ws.write(chunk)//读完了以后就写入
})
也可以直接使用管道流来完成这个操作。
管道流
rs.pipe(ws)
从rs(读的管道)直接插入到ws(写的管道)内。
Node事件
node也是单线程的,通过V8引擎提供的异步回调接口,通过这些接口可以处理大量的并发,性能会变高。
- 加载事件模块
let events=require("event");
- 创建eventEmitter对象,注意:这里就需要new了
let ee=new events.EventEmitter()
- 创建事件监听
ee.on("helloSucess",function(){ consloe.log("1111111") })
Os模块和path模块
路径模块
- 找到路径
let strPath="https://www.bilibili.com/video/BV1i7411G7kW?p=8"
- 获取路径信息的扩展名
let info=path.extname(strPath)//返回上一个路径的后缀名,例如.jpg
- 将一个路径或路径片段的序列解析为一个绝对路径(注意:写数组时需要解构再使用)
let arr=['/sxt','qianduan','zhongji'] let info1=parse.resolve(...arr)//拼接成了E:\sxt\qianduan\zhongji,当前的盘的位置是存储当前文件的根位置
- 路径拼接:
__dirname:获取当前执行目录。
先将地址进行解析,再将需要的部分进行切片,再将得到的部分拼接到需要的路径后。
let arrParse=str.split('/')//分割 arr=arrParse.slice(-2)//切片,只获取xinwen、guonei即可 let filepath=path.join(__dirname,...arr)//拼接后可访问当前执行目录下的/xinwen中的guonei.html
- 查找当前文件的扩展名:
与直接使用extname的不同是,这里会先找到当前文件,再进行扩展名获取
__filename:获取当前的执行文件
let filepath=path.extname(__filename)//返回.js
- 解析路径:
可以将路径信息直接解析出来。
解析出根路径,目录,扩展名,文件名。
path.parse(__filename)//返回当前文件的路径解析对象
补充:process.cwd():获取当前执行node命令时的文件夹目录名 。
系统模块
使用系统模块中的内容来随时获取系统信息,方便我们随时监测系统的情况,例如cpu的占有率过高会出现崩溃,那么我们是可以监测到并及时做出处理。
- 载入os模块
let os=require('os')
可以看到很多信息,这里举例cpu 。
- 获取操作系统的cpu信息
os.cpus()
如果console.log它,则会显示出一个数组,cpu是几核的,那么这个数组就会有几个元素,每个元素都是一个对象,这个对象显示了当前它对应核的参数信息。获得这些参数后,可以在node的手册中查找每个属性所对应的意思。
- 获取系统内存信息
console.log(os.totalmem())
返回当前系统的内存大小,单位:字节。
- 获取当前系统的架构
console.log(os.arch())
- 获取当前系统剩余的内存
console.log(os.freemem())
- 获取系统运行平台
console.log(os.platform())