Node.js基本内容复习
定义:Node.js是一个免费开源跨平台的JavaScript运行时环境,允许开发人员在浏览器之外编写命令行和服务器脚本
应用场景:
- 服务器端开发
- 底层平台,扩展性极好,兼容性和伸缩性做到了完美融合
- 周边生态 包管理工具(npm)
特点:
- 完全是js语法
- Node.js有超强高并发能力,可以实现高性能的服务器
- 开发周期短,学习成本低
基础
包
包实际上是一个压缩文件,解压以后还原为目录.
- package.json 包描述文件
- bin 可执行二进制文件
- lib js代码
- doc 文档
- test 单元测试
包来源:
Node.js中有内置模块和自定义模块,包是第三方开发出来的
包用途:
Node.js为我们提供了一些内置的模块api,导致在使用内置模块开发时,可能会设计底层的逻辑操作。
包可以提供更高级、便捷的强大API,极大提高了程序开发的效率包和内置模块的关系
npm
npm由来
最早时候是个人为了扩展功能做了一些包,放到社区,为了让大家能统一,由此诞生了npm
NPM(Node Package Manager)node包管理工具
思路
创建一个代码仓库,里面存放了全部必须要被共享的代码
通知JQ,BootStrap的作者,让他们把代码提交到仓库中,而后分别给他们取个名字
当有人想使用这些代码时,就能使用npm来下载代码了
这些被使用的代码就叫做包[package],这也是npm的由来
发展
npm的发展和node.js的发展相辅相成,node.js缺乏一个包管理工具,最后node.js内置了npm
npm 命令
# 单一包安装
npm install 包名<@版本号>
简写 i
# 安装已经配置的所有包,后续初始化node会生成,package.json
npm i
常用命令
npm help 查看帮助npm命令列表
npm -l 查看各个命令的简单用法
npm -v 查看npm版本
npm init: npm init命令用于项目初始化,在项目目录中会生成一个文件package.json,这个文件是之后当前项目的配置文件,也成为初始化Node
强制新建项目 在初始化项目时,使用参数 -f (代表force), -y(代表yes),会跳过左右的提问阶段,直接生成一个新的文件package.json
npm list: npm list 命令以树形结构列出全局安装的所有模块
npm i 安装
运行代码
npm run xxx
npm不仅仅可以用来模块管理,还可以用于执行脚本,需要执行的脚本时在package.json这个文件的script字段中
控制台运行
npm run dev 等于运行于 node first.js
初始化node
初始化步骤
- 新建一个空文件夹,作为Node项目的根目录
- 在文件夹中打开控制台
- 输入命令完成项目根目录初始化
npm镜像切换
镜像概念
cnpm
淘宝前端团队发起并维护,cnpm是专门为node.js打造的国内镜像站。
目的是为了npm包的下载,也称为"淘宝镜像"
cnpm使用
两种使用方式
- 基于cnpm命令行工具
- 直接修改npm的配置
基于cnpm命令行工具
npm install -g cnpm --registry=http://registry.npm.taobao.org
直接修改npm的配置
使用npm config 命令修改
npm config set registry http://registry.npm.taobao.org
监测镜像是否修改成功
npm config get registry
全局安装和局部安装的细节
在项目中使用一个包时会首先试用局部安装的包,即(当前项目package.json里面下载的包), 如果项目中没有这个包,则就会去全局下载包中寻找是否有对应包
全局安装值得时将下载的包放到npm目录中,这样这台电脑的项目都能用
而没有 -g 参数,所有包都放在和package.json
同级目录中的node-modules
文件夹下,下载的包只有当前目录可用
开发依赖和生产依赖
npm下载的包会分为两个类型,开发依赖和生产依赖两种包
开发依赖
在package.json
中会新建一个devDependecies
对象,在这个对象中写入的包称为
“开发依赖包”,这里的包主要是为了加快开发效率,实际项目启动后是不需要的。到时候我们会在项目完成后忽略开发依赖包,比如babel
,webpack
等
//某一个项目的开发依赖
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-service": "~5.0.0"
}
生产依赖
是指在项目启动后必须要用的包,会在package.json
中的dependecies
对象中(没有会新建),写在这个对象中的所有包,我们称为“生产依赖包”,运行项目期间这些包都存在,项目上线后也存在,比如jquery
,vue
等
//某一个项目的生产依赖
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13",
"vue-router": "^4.2.4"
}
设置依赖
npm 下载包的时候,就可以设定时开发依赖还是生产依赖
npm install 包名称 -D
-D或--save-dev
:是指下载包为开发依赖
默认或-S或--save
:指的是下载的包为生产依赖
nrm
在使用npm下载包的时候,如果注册的镜像网站网速慢,则我们就需要切换镜像源。为了方便切换我们可以安装一个工具nrm,用这个工具快速切换镜像源
安装nrm
npm install nrm -g
nrm ls
模块化
概念
在变成过程中的模块化,本质上就是遵守一个固定的规则,把一个大文件拆分成多个独立且相互依赖的小模块
提高模块的好处:
- 提高了代码的复用性
- 减低了代码的耦合性
- 提高了代码后期的可维护性
Node.js模块分类
在Node.js中所有的jw文件都可以被称为一个模块
Node.js中根据模块来源不同,可以将模块分为三类
- 内置模块:由Node.js在安装时自带的模块,由官方提供,如fs,path,http
- 自定义模块:自己编写的js文件,如index.js,app.js
- 第三方模块(中间件) 由其他公司人员开发出来并共享供大家使用的模块,称为第三方模块
加载模块
则需要使用Node.js提供的一个加载命令:require(模块路径)
// 加载内置模块
require("内置模块名称")
// 加载自定义模块
require("模块路径+自定义模块名称")
// 加载第三方模块
// 加载前需要先从npm服务器上下载到mode_modulse中
require("第三方模块名称")
// 加载内置模块
const fs = require("fs")
// 加载自定义模块
const home = require("./home.js")
// 加载第三方模块
// 先 npm install moment
const moment = require("moment")
暴露模块
在三种模块类型中,内置模块和第三方模块直接引用,我们只需要加载使用。
而自定义模块我们需要require
来引入使用,但对于自定义模块需要在代码中写一个外部可访问的代码
module
在每一js自定义模块中都会带有一个module对象,它里面存储了与当前模块的一些信息
部分属性:
id
:当前模块ID编号,默认.
path
:模块路径
filename
:模块完整路径
children
:子模块,表示当前模块中已经加载的子模块,默认为空数组
paths
:数组形式,完成模块的个路径
loaded
:布尔值,默认false,表示模块是否加载完毕
export
:自定义模块module中最重要的属性,所有需要暴露的接口都会放在这个号对象中,共享出去
解释:所有的js文件在通过require引入加载模块时,其实真正加载得到的是module.exports中的所有对象,所以暴露模块是把需要提供给外部使用的内容写道exports对象中
暴露module.exports
暴露模块就是暴露js中的变量和函数
module.exports.变量名 = 变量值
module.exports.函数名 = 函数体
// 暴露时完成定义值和函数声明
module.exports.num = 10
module.exports.show = function(){
console.log("fuction show")
}
exports 对象
我们发现在暴露模块文件中,如果有更多个变量和或函数需要暴露,则需要写更多的module.exports
,那有没有简便少写一点的代码呢?有的
为了简化写法,Node提供了一个exports
读写对象
默认情况下,exports
=module.exports
即他们指向的是同一个对象
exports.num = 100
console.log(exports === module.exports) // true
解构暴露写法
如果对于多次exports
的书写,可以做简写,就是在暴露时采用exports.defalut
方法集中一个对象暴露,而在加载引入时同时使用对象的方式接受部分属性,这样的方法叫做
解构暴露
// 解构暴露A.js
const name = "tom"
const age = 22
const show = function(){
return "welcom" + name
}
// 建立新对象,完成对exports对象的覆盖
module.exports = {
name,
age,
show
}
// B.js
// 直接以对象的方式接收,并且把对象中的同名值的数据传递
const {name,age,show} = require("./A.js")
console.log(name)
console.log(age)
const cc = show()
console.log(cc)
在完成导出时没有必要把所有值都解构出,我们只要解构的值
颜色是不同的,在解构暴露时对变量的位置是没有要求的。因为对应的是变量的属性名和函数名
文件系统
fs模块介绍
node.js中的文件系统模块(fs)的方法存在同步和异步两个版本
在方法名字后面又Sync
的都是同步操作
// 引入模块
const fs = require("fs")
同步和异步区别
同步读取文件:就是当程序在读取文件的时候,程序会等待读取的返回结果(即文件内容),直到所有文件内容全部读取完毕了才继续向下执行,所以程序的执行顺序是逐一执行的。没有任何代码的跳跃
异步读取文件:程序在异步读取文件时,不等待执行结果,继续执行其他代码。如果异步读取的代码获取到了再完成显示或处理。异步读取的返回时间点是一个不可等待的时间。所以书写的代码有规定的地点,我们把这个地点叫做**“回调函数”**
读取文件
为了统一文件位置,我们把数据文件都建立在data/
文件夹里
同步读取
const data = fs.readFileSync("文件路径")
// 加载
let fs = require("fs")
console.log("开始读取文件")
// 同步读取文件,将读取到的数据返回存储在data中
const data = fs.readFileSync("./data/a.txt")
// 展示
console.log(`data:${data}`)
console.log('读取文件结束')
异步读取
fs.readFile("文件路径",function(错误对象,正确对象){
回调函数体
})
// 引入
let fs = require("fs")
console.log("异步读取开始")
// 由于异步读取对象的返回是不确定时间,所以第二个参数用来读取与不反悔
fs.readFile("./data/a.txt" function(err,data){
if(err){
console.log(err)
return
}
console.log("异步读取到" + data.toString())
})
console.log("异步读取文件结束")
异步读取文件后回调函数执行会在所有其他代码做完之后。这也是异步程序的一个特点,javascript中有很多这样的回调函数的代码处理,比如setTimeout,setInterver,onclick等
同步异步比较
同步相对符合代码逻辑顺序,但程序运行速度相对比异步慢,因为有阻塞
异步读取从性能上相对高,程序的整体运行速度也是比较快,没有阻塞
读取文件的编码类型
默认fs模块编码类型是utf-8,也可以手动指定,作为第二个参数
fs.readFile("./data/a.txt", "utf-8", function(err,data) {
if(err){
console.log(err)
return
}
console.log("异步读取到" + data.toString())
})
// 读取二进制格式文件
// 图片
fs.readFile(ImgPath,"binary",function(err,data){})
写入文件
// 异步
fs.writeFile("路径","要写入的数据","参数对象","回调函数")
// 同步
fs.writeFileSync("文件路径",要写入的数据)
参数说明:
文件路径 数据需要写入的文件位置
要写入的数据 数据可以是String格式也可以是buffer(缓冲)对象
参数对象 可以省略,对象包含{编码类型},默认utf-8
回调函数 此函数只有一个参数err,在写入失败的时候返回
异步写入
// 引入文件
const fs = require("fs")
// 需要写入内容
const text = "敌方还有三十秒到达战场"
//
fs.writeFile("./data/b.txt", text,err => {
if(err){
return console.error(err)
}
console.log("写入成功")
})
代码说明
b.txt 如果不存在会自动新建,如果存在则会覆盖之前里面的所有内容
text 就是要写入的内容,这里是string类型
err 使用了箭头函数写法,写入失败会进入if语句进行显示错误信息,并return终止程序继续向下运行
同步写入
const fs = require("fs")
fs.writeFileSync("./data/A.txt","紧急集合")
writeFileSync没有返回值,所以不需要使用变量接受
文件的复制与粘贴
文件的复制与粘贴就是对文件的读取和写入的合并操作
获取绝对路径
// 获取当前文件所在目录的绝对路径(目录)
console.log(__dirname)
// 获取当前文件的绝对路径(目录 + 文件名)
console.log(__filename)
读入流和输出流
将一个文件直接从读入流读入,同时利用管道符将这个文件写入到输出流
const fs = require("fs")
// 文本操作
cws = fs.createWriteStream("./data/newcc.txt")
fs.createReadStream("./data/newc.txt").pipe(cws) // pipe管道
// 图片操作
cws = fs.createWriteStream("./data/newcc.png")
fs.createReadStream("./data/newc.png").pipe(cws)
// 复制操作
fs.copyFile("./data.a.txt","./data2/newA.txt",err => {
if(err){
console.log(err)
}
else{
let result = fs.readFileSync("./data2/newA.txt","utf-8")
console.log(result)
}
})
// 删除操作
fs.unlink('./data2/newA.txt, err =>{
if(err){
console.log(err)
return
}
console.log("文件删除")
})
// 删除目录
注意:非空目录删除
// 删除文件
fs.rmdir("./data2", err => {
if(err)
{
console.log(err)
return
}
console.log("目录删除")
})
// 写入追加文件
fs.appendFile("./data2/a.txt","world",(err) => {
if (err) {
console.log(err);
}
else {
console.log(
fs.readFileSync("example_file.txt", "utf8"));
})
CSV
介绍
csv(Comma-Separated Values) 逗号分隔符,也称为字符分隔值,是一种以纯文本心事用逗号分隔的字符串内容,文件的后缀名是.csv
csv文件是可以使用Excel打开的,展现为一个表格形态。所以常作为软件数据的导入和导出格式。
csv格式转换
在编程过程中常用的数据类型是json对象形式,而我们写入的文件格式是需要csv字符串格式。所以我们需要格式转换
json2csv
安装插件
npm i json2csv
如果安装插件前,没有npm init
初始化,就只会简单生成
package.json中生产依赖部分的插件版本
{
"dependencies": {
"json2csv": "^6.0.0-alpha.2"
}
}
同时也会生成node_modules
目录,单独下载必要的插件,这样保证能单独加载引入使用
所以还是在安装插件前先npm init
初始化下,这样比较规范
语法
const json2csv = require("json2csv")
let csvStr = new json2csv.Parser({第一行表头字符串}).parse(对象数组字符串)
示例
//载入第三方库
const json2csv = require("json2csv")
//载入fs模块
const fs = require('fs')
//1.获取数据
let filmAllList=[
{
"_id":1,"filmName":"1921","filmPrice":"38.88","filmScore":40,"filmImg":"https://image11.m1905.cn/uploadfile/2023/0727/thumb_1_300_406_20230727021216146898.jpg","filmType":"历史","boxOffice":18
},
{
"_id":2,"filmName":"封神","filmPrice":"68.88","filmScore":80,"filmImg":"https://image11.m1905.cn/uploadfile/2023/0719/thumb_1_300_406_20230719013959368448.jpg","filmType":"玄幻","boxOffice":18
},
{
"_id":3,"filmName":"蜘蛛侠","filmPrice":"28.88","filmScore":100,"filmImg":"https://image11.m1905.cn/uploadfile/2021/0430/thumb_1_300_406_20210430102850977848.jpg","filmType":"科幻","boxOffice":18
}
]
// 2.将json对象转换成csv字符串
let fields = [
["_id","filmName","filmPrice","filmScore","filmImg","filmType","boxOffice"];//设置第一行数据,即列头
]
let csvStr = new json2csv.Parser({fields}).parse(filmAllList)
// 3.将csv格式字符串写道file.csv文件中
let filePath = __dirname + "/data/file.csv"
// 同步
fs.writeFileSync(filePath.csvStr)
// 写入完成
console.log("写入完成")
解析:
new json2csv.Parser({fields})
生成一个解析对象,参数是一个对象,对象中是需要的第一行数据,返回的依然是一个Parser对象,通过该对象的parse方法可以返回一个csv格式字符串
csvtojson
将csv文件中的数据转换成对象数据
需要安装插件csvtojson
npm i csvtojson
let csvtojson = require("csvtojson")
// fromFile函数返回的是一个promise的then异步处理
csvtojson().fromFile("./data/file.csv").then(data => {
console.log(data)
})
加载进来csvtojson是一个函数,返回一个内置转换器对象Converter,此对象带有一个formFile函数,函数中给出csv文件的路径,formFile函数返回一个Promise对象,我们利用then来进行异步数据的接受
既然返回的是Promise对象,我们可以使用async/await的语法糖来封装
let csvtojson = require("csvtojson")
async function changeCSV(){
let fileList = await csvtojson().fromFile("./data/file.csv")
console.log(fileList)
}
changeCSV()
// 结果相同
path模块
概念
path模块是node.js的内置模块,用来处理路径问题
const path = require("path")
path模块引入一个path对象
path-常用api
basename
返回文件名或文件名+扩展名
path.basename()
方法就返回指定路径的最后一部分
const path = require("path")
// 完整路径
const myPath = "/aa/bb/cc/mysong.mp3"
// 获取路径
console.log(path.basename(myPath)) // mysong.mp3
// 也可以指定扩展名,完成文件名的返回
console.log(path.basename(myPath,".mp3")) // 忽略song
dirname
返回完整目录,尾部目录分隔符会被忽略
const path = require("path")
let myPath = "/aa/bb/cc/dd/mysong.mp3"
console.log(path.dirname(myPath)) // 输出 /aa/bb/cc/dd 最后的斜杠不输出
extname
返回扩展名,从最后一个点后面的内容
const path = require('path');
const myPath = "/aa/bb/cc/mysong.mp3";
console.log(path.extname(myPath)); //返回 .mp3
join
将不同字符串连接为一个完整的路径
const path = require('path');
console.log(path.join('image','aa','cc'));// image\aa\cc
console.log(path.join(__dirname + "/img/1.jpg"));
resolve
将路径或路径片段直接转换为绝对路径
const path = require("path")
// 解析当前目录下路径
console.log(path.resolve("image","aa"));// D:\node\node-study\第5张-path模块\image\aa
//盘符根目录下路径
console.log(path.resolve("/image",'bb')); // D:\image\bb
format
可以将一个路径对象组合成一个字符串
const path = require("path")
const format_str = path.format({
dir:"C:\\images\\aa",
base:"my.jpg"
})
console.log(format_str) // C:\images\aa\my.jpg