node
1、NPM 使用介绍
本文介绍了 Node.js 中 NPM 的使用,我们先来了解什么是 NPM。
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
2、express
服务框架
npm install express # 本地安装
//本地安装,会生成node_modules文件
npm install express -g # 全局安装
//全局安装,安装在了这个地址,C:\Users\用户\AppData\Roaming\npm
要改淘宝镜像,安装时地址failed,淘宝镜像可能改了。
两种方法
1.cnpm命令行工具代替npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
2.命令行设置将npm地址修改为淘宝镜像源
npm config set registry https://registry.npm.taobao.org
简单案例
let express = require('express');
let app = express()
app.get('/',(req,res)=>{
res.send("这是首页")
})
app.listen(8080,()=>{
console.log("服务器启动:",'http://localhost:8080/')
})
然后终端打开,node demo2.js 运行
3、模块导入与导出
//index1.js
function fn(){
console.log('fn')
}
let student = {
username:"老陈"
}
console.log('student:',student.username)
// module.exports = {student,fn}
//函数需要导出才能用
exports.fn = fn;
//index2.js
//绝对路径
let file1 = require('./index1.js')
console.log('file1',file1)
//调用index.js,函数fn
file1.fn()
效果
4、模块路径
node_modules 目录
let express = require('foo/ba')
NodeJS 定义了一个特殊的 node_modules 目录用于存放模块。例如某个模块的绝对路径是 /home/user/hello.js,在该模块中使用 require(‘foo/bar’) 方式加载模块时,则 NodeJS 依次尝试使用以下路径。
/home/user/node_modules/foo/bar
/home/node_modules/foo/bar
/node_modules/foo/bar
NODE_PATH 环境变量
与 PATH 环境变量类似,NodeJS 允许通过 NODE_PATH 环境变量来指定额外的模块搜索路径。NODE_PATH 环境变量中包含一到多个目录路径,路径之间在 Linux 下使用:分隔,在 Windows 下使用;分隔。例如定义了以下 NODE_PATH 环境变量:
NODE_PATH=/home/user/lib:/home/lib
当使用 require(‘foo/bar’)的方式加载模块时,则 NodeJS 依次尝试以下路径。
/home/user/lib/foo/bar
/home/lib/foo/bar
5、nodejs包
包结构
包实际上是一个存档文件,即一个目录直接打包为.zip或tar.gz格式的文件,安装后解压还原为目录。完全符合CommonJS规范的包目录应该 包含如下这些文件。
1、package.json:包描述文件
2、bin:用于存放可执行二进制文件的目录
3、lib:用于存放JavaScript代码的目录
4、doc:用于存放文档的目录
5、test:用于存放单元测试用例的代码
node_modules里面的express
npm init,初始化配置
翻译
包的名称
包的版本
包的描述
包的执行文件
yes,确认
然后就能在package.json看到这些内容
6、文件同步写入
同步openSync
let fs = require('fs')
// 同步打开文件
let fd = fs.openSync('text1.html','w')
// 写入内容
let str = "<h1>你好!</h1>"
fs.writeFileSync(fd,str);
// 退出文件
fs.closeSync(fd)
然后就会创建一个html文件
7、文件异步写入
异步open
let fs = require('fs')
fs.open('text2.txt','w',(err,fd)=>{
console.log("文件打开")
fs.writeFile(fd,'你好',function(err){
if(!err){
console.log("写入完成!")
fs.close(fd,()=>{
console.log("文件关闭完成")
})
}else{
console.log(err)
}
})
})
console.log('123')
// 同步:点汉堡-》制作汉堡-》汉堡制作好之后,你拿走了。-》下一位用户继续点汉堡
// 异步:点汉堡-》旁边等候->下一位用户继续点汉堡-》旁边等候。汉堡好了之后,会自动叫你领取。
异步函数,会先输出123,再执行其他函数
8、文件流写入,createWriteStream
let fs = require('fs');
// 创建写入流
let ws = fs.createWriteStream('text3.txt');
// 监听通道打开
ws.once('open',()=>{
console.log("通道打开");
ws.write('你吃饭了吗1?')
ws.write('你吃饭了吗2?')
ws.write('你吃饭了吗3?')
// 写入结束
ws.end()
})
// 监听通道关闭,once表示监听一次
ws.once('close',()=>{
console.log('通道关闭')
})
text文件
9、文件读取,readFile
let fs = require('fs')
fs.readFile('text1.html',(err,data)=>{
if(!err){
console.log(data.toString())
//toString()转化字符串,如果直接输出data,默认时二进制数据
}else{
console.log('err',err)
}
})
console.log('读取数据')
读取文件,然后复制后替换其他文件,readFile读取,writeFile写入
let fs = require('fs')
fs.readFile('大炮.png',(err,data)=>{
if(!err){
console.log(data)
//复制大炮,改名字为小炮
fs.writeFile('小炮.png',data,(err)=>{
if(!err){
console.log('图片读取写入成功')
}else{
console.log('err',err)
}
})
}else{
console.log('err',err)
}
})
10、文件的读取和写入流以及管道
读取图片,然后重命名再写入图片
createReadStream
读取
createWriteStream
写入
let fs = require('fs')
let rs = fs.createReadStream('大炮.png');
let ws = fs.createWriteStream('中泡.png');
// 监听读取流打开
rs.once('open',function(){
console.log('监听读取流')
})
// 监听读取流关闭
rs.once('close',function(){
console.log('读取流关闭')
// 在 rs.once('close') 中调用 ws.end() 会触发写入流的关闭,因为 ws.end() 显式地关闭了写入流。
// ws.end()
})
// 监听写入流打开
ws.once('open',function(){
console.log('监听写入流')
})
// 监听读写入关闭
ws.once('close',function(){
console.log('写入流关闭')
})
// 监听到数据data,将读取的数据通过写入流写入(将大炮的图片复制,再改名为重炮)
rs.on('data',(data)=>{
ws.write(data)
})
管道(简单化,一样效果)
let fs = require('fs')
let rs = fs.createReadStream('大炮.png');
let ws = fs.createWriteStream('重炮.png');
// 创建管道,将读取流通过管道流出
rs.pipe(ws)
11、删除文件和读取目录下文件
unlink
删除
readdir
读取
let fs = require('fs');
// 删除文件
// fs.unlink('text1.html',(err)=>{
// if(err){
// console.log(err)
// }else{
// console.log('删除文件成功')
// }
// })
// 读取目录下的所有文件
fs.readdir('./',(err,files)=>{
if(err){
console.log(err)
}else{
console.log(files)
}
})
12、创建删除目录、递归删除非空目录
mkdir
创建
rmdir
删除
let fs = require('fs')
// 创建文件夹
// fs.mkdir('./img',(err)=>{
// if(err){
// console.log(err)
// }else{
// console.log('创建成功')
// }
// })
// 删除文件夹
fs.rmdir('./img',(err)=>{
if(err){
console.log(err)
}else{
console.log('文件夹删除成功')
}
})
非空目录
let fs = require('fs')
function delDir(dirPath){
// 读取目录
var filesArr = fs.readdirSync(dirPath);
// 拿到目录的文件,然后循环
for (var i in filesArr){
// 把目录拼接出来
var filePath = dirPath+'/'+filesArr[i];
// 读取文件信息
var stat = fs.statSync(filePath);
// 判断是文件还是目录,node的语法
if(stat.isFile()){
// 删除
fs.unlinkSync(filePath)
}else if(stat.isDirectory()){
// 递归调用自己,再循环
delDir(filePath)
}
}
// 删除空目录
fs.rmdirSync(dirPath)
}
delDir('./img')
13、node事件触发
创建文件夹后,触发事件
let fs = require('fs')
let events = require('events')
// 创建事件对象
var eventLog = new events.EventEmitter();
// 监听事件
eventLog.on('lcMkDir',function(msg){
console.log('创建目录事件触发1',msg)
})
eventLog.on('lcMkDir',function(msg){
console.log('创建目录事件触发2',msg)
})
eventLog.on('lcMkDir',function(msg){
console.log('创建目录事件触发3',msg)
})
// 触发事件
console.log('over')
// 创建文件夹
fs.mkdir('./img',(err)=>{
if(err){
console.log(err)
}else{
console.log('创建成功')
//传参,msg
eventLog.emit("lcMkDir","你好")
}
})
14、buffer缓冲区
多用于人工智能
// 将字符串放置到缓冲区
let b1 = Buffer.from('10')
console.log(b1)
//转化二级制
console.log(b1.toString())
// 初始化缓冲区,创建一个大小为10个字节的缓冲区
// 保证新创建的缓冲区数据是不会包含旧的数据
let b2 = Buffer.alloc(10)
console.log(b2)
// 不会重置数据,不太安全,需要谨慎使用
let b3 = Buffer.allocUnsafe(10)
console.log(b3)
b3[0] = 3
console.log(b3)
console.log(b3[0].toString())
15、多进程之exec
通过main1.js,打开index1.js
//index1.js
console.log('进程:' + process.argv[2] + "执行。")
//main1.js
const child_process = require('child_process');
for(var i = 0;i<3;i++){
// stdout子进程的输出结果
// stderr子进程输出的错误
var workerProcess = child_process.exec('node index1.js '+i,function(err,stdout,stderr){
if(err){
console.log(err)
}else{
console.log('stdout:',stdout)
console.log('stderr:',stderr)
}
})
workerProcess.on('exit',function(code){
console.log('子进程已退出,退出码:'+code)
})
}
16、多进程之fork与spawn
spawn
//index1.js
console.log('进程:' + process.argv[2] + "执行。")
const child_process = require('child_process');
for(var i = 0;i<3;i++){
// stdout子进程的输出结果
// stderr子进程输出的错误
var workerProcess = child_process.spawn('node',['index1.js',i])
// 监听数据
workerProcess.stdout.on('data',function(data){
console.log('data:'+data)
})
// 监听错误
workerProcess.stderr.on('data',function(data){
console.log('err:'+data)
})
// 监听关闭
workerProcess.on('close',function(code){
console.log('子进程已退出,退出码:'+code)
})
}
fork
const child_process = require('child_process');
for(var i = 0;i<3;i++){
// stdout子进程的输出结果
// stderr子进程输出的错误
var workerProcess = child_process.fork('index1.js',[i])
workerProcess.on('close',function(code){
console.log('子进程已退出,退出码:'+code)
})
}
17、node模块path
console.log(__filename)//当前正在执行的脚本的文件名称
console.log(__dirname)//当前正在执行脚本的目录名称
let path = require('path')
//文件路径的例子
let strPath = 'E:/share/Node/node/代码/demo6/index1.png'
// 获取扩展名
console.log(path.extname(strPath)) //.png
console.log(path.extname(__filename))//.js
// 获取文件名称
console.log(path.basename(strPath))//index1.png
console.log(path.basename(__filename))//index1.js
// 获取目录名称
console.log(path.dirname(strPath))//E:/share/Node/node/代码/demo6
console.log(path.dirname(__filename))//C:\Users\VAEVBWERV\Documents\企业级项目代码\node\代码\demo6
// 路径解析和规范化路径
console.log(path.normalize(strPath))//E:\share\Node\node\代码\demo6\index1.png
// 路径合并
console.log(path.join( __dirname+'/abc.png') )//C:\Users\VAEVBWERV\Documents\企业级项目代码\node\代码\demo6\abc.png
// 获取绝对路径的合并
console.log(path.resolve( __dirname+'/abc.png') )//C:\Users\VAEVBWERV\Documents\企业级项目代码\node\代码\demo6\abc.png
18、网络通信
协议是网络中计算机或设备之间进行通信的一系列规则的集合。常用协议有IP、TCP、HTTP、POP3、SMTP等。
Get请求例子,使用Charles抓取的request:
#
GET /562f25980001b1b106000338.jpg HTTP/1.1
Host img.mukewang.com
User-Agent Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept image/webp,image/*,*/*;q=0.8
Referer http://www.imooc.com/
Accept-Encoding gzip, deflate, sdch
Accept-Language zh-CN,zh;q=0.8
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本.
GET说明请求类型为GET,[/562f25980001b1b106000338.jpg]为要访问的资源,该行的最后一部分说明使用的是HTTP1.1版本。
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
从第二行起为请求头部,HOST将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等
第三部分:空行,请求头部后面的空行是必须的
即使第四部分的请求数据为空,也必须有空行。
第四部分:请求数据也叫主体,可以添加任意的其他数据。
这个例子的请求数据为空。
POST请求例子,使用Charles抓取的request:
#
POST / HTTP1.1
Host:www.wrox.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
第一部分:请求行,第一行明了是post请求,以及http1.1版本。 第二部分:请求头部,第二行至第六行。 第三部分:空行,第七行的空行。 第四部分:请求数据,第八行。
19、HTTP模块搭建简易服务器
通过地址返回内容
// 导入node的HTTP模块
let http = require('http');
// 创建服务器实例
let server = http.createServer();
// 服务器监听请求数据
server.on('request',(req,res)=>{
console.log(req.url)
if(req.url=='/'){
res.end('index')
}else if(req.url=='/login'){
res.end('login page')
}else{
res.end('404 not found')
}
})
// 绑定监听的端口号
server.listen(3000,()=>{
console.log('服务器启动:',"http://127.0.0.1:3000")
})
20、express实现静态服务器和自定义接口
当你在浏览器中访问 http://127.0.0.1:3000 时,服务器会自动打开 index.html 页面,这是因为 Express 的静态文件服务 (express.static) 默认会寻找并返回 index.html 文件作为根路径 (/) 的响应。
具体原因
静态文件服务:
在你的代码中,app.use(express.static(“static”)) 将 static 目录设置为静态资源目录。Express 会将该目录下的文件作为静态资源提供给客户端。
默认文件:
当访问根路径 / 时,Express 会默认查找 index.html 文件并返回。这是因为 index.html 是静态文件服务的默认入口文件。
文件结构:
假设你的项目目录结构如下:
复制
project/
├── app.js
└── static/
├── index.html
└── css/
└── style.css
当你访问 http://127.0.0.1:3000 时,Express 会在 static 目录下查找 index.html 文件并返回。
浏览器行为:
浏览器在访问根路径时,默认会请求 /,而 Express 会返回 index.html 文件,因此页面会自动加载。
node app.js打开
//app.js
// 导入express框架
let express = require('express')
// 实例化服务器应用
let app = express()
// 实现静态服务器
app.use(express.static("static"))
// 实现自定义接口
app.get('/api/userlist',(req,res)=>{
// 请求的信息:req对象
// 响应的操作和信息:res对象
res.json({
state:"ok",
userList:[
{username:"小明",sex:"男"},
{username:"小黑",sex:"男"},
{username:"小白",sex:"女"}
]
})
})
// 启动服务器
app.listen(3000,()=>{
console.log("服务器启动","http://127.0.0.1:3000")
})
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1 class="bg">hello</h1>
<script>
fetch('/api/userlist').then((res)=>{
return res.json()
}).then((res)=>{
console.log(res)
res.userList.forEach((item,i)=>{
let newDiv = document.createElement('div')
newDiv.innerHTML = item.username+"的性别是"+item.sex
document.body.appendChild(newDiv)
})
})
</script>
</body>
</html>