node基础

发布于:2025-03-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

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等。
img

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>

在这里插入图片描述