nodejs入门基础(复习)

https://study.163.com/course/courseLearn.htm?courseId=1210098848#/learn/video?lessonId=1281066155&courseId=1210098848

nodejs基础学习

文章目录

  • nodejs基础学习
      • node初识
      • nodejs安装
      • nodejs REPL交互解释器
    • nodejs编辑器和npm
      • node的模块运行机制
      • nodejs模块路径
      • nodejs的包
      • nodejs的文件系统
        • 同步写
        • 异步写
        • 文件流写
        • 异步读
        • 异步读写文件
        • 流读写文件
        • 使用pipe管道来读写流
      • 通过node删除文件、读取文件目录
      • 创建删除目录
      • node 的事件机制
        • 定义与触发事件
      • Buffer二进制数据缓冲区操作
      • node的多进程
        • exec
        • spawn
        • fork
      • path路径
      • 网络通信原理
      • 理解HTTP协议
      • nodejs的HTTP模块
      • nodejs使用express

node初识

node.js是基于JavaScript的运行环境,使用的是google v8的引擎

使用事件驱动和异步的非阻塞I/O模型

前端学习会比较方便,因为语言语法是一样的,只是api不一样,面向的功能不一样,对于前段来说可以简单的去定义接口api

nodejs安装

可以参考菜鸟教程的nodejs安装,个人觉得写得很详细了,而且电脑已经安装过就不实操了

https://www.runoob.com/nodejs/nodejs-install-setup.html

nodejs REPL交互解释器

在命令行中输入node之后会打开交互解释器

类似浏览器的控制台的使用

下划线_可以方便的复制上一条输出

另外.help里面还有很多方法

nodejs编辑器和npm

直接在vscode中创建js文件,正常执行即可,也可以用vscode的插件

node demo1.js

npm一般是包括在nodejs中的,是我们对项目依赖包的快速下载

记得安装淘宝镜像源

nodejs入门基础(复习)_第1张图片

npm install XXX -g全局安装

npm install XXX --save依赖到项目

下面试一下express

新建demo01.js

// 使用express和npm
// npm install express --save
let express=require('express')
let app=express()
app.get('/',(req,res)=>{
    res.send('hello')
})

app.listen(8000,()=>{
    console.log("启动",'http://localhost:8000')
})

在命令行运行

node demo01.js

nodejs入门基础(复习)_第2张图片

node的模块运行机制

commonjs

文件即模块

通过require引入exports导出的模块

新建demo02

nodejs入门基础(复习)_第3张图片

nodejs入门基础(复习)_第4张图片

也可以这样导出

nodejs入门基础(复习)_第5张图片

nodejs入门基础(复习)_第6张图片

不过还是推荐用module.exports的形式优先级要高一些而且两种同时用会乱掉

nodejs模块路径

在require中使用相对路径引用自己写的文件

如果没有相对路径会优先找当前目录下的node_modules,逐级往上找

nodejs的包

就是我们node_modules中的一个目录形成的模块,配置信息一般在package.json

nodejs入门基础(复习)_第7张图片

npm init 用来自定初始化包

nodejs的文件系统

nodejs是服务器语言,所以一定可以使用file

即node中的fs模块

const fs = require('fs')

新建demo03

同步写

下面先使用同步的方式来写入一个文件(等待写入完成才会有下一步)

const fs =require('fs')

//同步打开文件
let fd=fs.openSync('./test1.txt','w')
console.log(fd)

//写入内容
let str ='hello\n'
fs.writeFileSync(fd,str)

//退出文件
fs.closeSync(fd)

nodejs入门基础(复习)_第8张图片

异步写

下面来试试异步的文件写入

const fs =require('fs')

//异步打开,使用回调函数
fs.open('text2.txt','w',(err,fd)=>{
    fs.writeFile(fd,'hello2',(err)=>{
        if(err){
            console.log(err)
        }
        fs.close(fd,(err)=>{
            if(err){
                console.log(err)
            }
            console.log('关闭完成')
        })
    })
})

console.log('index2')

nodejs入门基础(复习)_第9张图片

下面是同步和异步的区别

同步和异步是相对于操作结果来说,会不会等待结果返回

阻塞就是在等待时你不可以去干其他的事情,非阻塞就是在同样的情况下,可以同时去干其他的事情。阻塞和非阻塞是相对于线程是否被阻塞。

文件流写

文件还可以使用流写入

nodejs入门基础(复习)_第10张图片

异步读

nodejs入门基础(复习)_第11张图片

读出来的是buffer二进制数据的形式,转化成字符串就行了

nodejs入门基础(复习)_第12张图片

下面尝试把一张图片读入再写入

异步读写文件

新建index5.js,引入test.png

nodejs入门基础(复习)_第13张图片

流读写文件

nodejs入门基础(复习)_第14张图片

使用pipe管道来读写流
let fs=require('fs')
let rs=fs.createReadStream('./test.png')
let ws=fs.createWriteStream('./test_p.png')
//创建管道,读取流入到管道到写出流
rs.pipe(ws)
console.log('index7')

和上面index6的效果一样但是简便很多,用到pipe管道函数

通过node删除文件、读取文件目录

同样是使用fs文件系统

nodejs入门基础(复习)_第15张图片

删除文件用unlink,读取目录用readdir

nodejs入门基础(复习)_第16张图片

创建删除目录

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('目录删除成功')
    }
})

但是如果目录下面有文件,是不能直接删除的,所以需要我们递归把目录下的子级目录和文件删除

新建一个目录

nodejs入门基础(复习)_第17张图片

let fs = require("fs");

//删除非空目录(使用递归)
function delDir(dirPath) {
  let fileArr = fs.readdirSync(dirPath);
  //拿到目录列表
  console.log(dirPath + "~目录列表:", fileArr);
  fileArr.forEach((item) => {
    //可能是文件或者目录
    let filePath = dirPath + "/" + item;
    console.log(dirPath + ":", filePath);
    //读取文件或目录信息
    let stat = fs.statSync(filePath);
    if (stat.isFile()) {
      fs.unlinkSync(filePath);
    } else if (stat.isDirectory()) {
      delDir(filePath);
    }
  });
  //删除本目录
  fs.rmdirSync(dirPath);
}
delDir("./目录");
console.log("index10");

//控制台输出如下
PS D:\准备\老陈安排\nodejs基础\demo03> node index10.js
./目录~目录列表: [ 'text1.txt', 'text2.txt', 'text3.txt', '目录1', '目录2' ]
./目录: ./目录/text1.txt
./目录: ./目录/text2.txt
./目录: ./目录/text3.txt
./目录: ./目录/目录1
./目录/目录1~目录列表: [ 'text1.txt', '目录4' ]
./目录/目录1: ./目录/目录1/text1.txt
./目录/目录1: ./目录/目录1/目录4
./目录/目录1/目录4~目录列表: []
./目录: ./目录/目录2
./目录/目录2~目录列表: [ 'text2.txt', '目录3' ]
./目录/目录2: ./目录/目录2/text2.txt
./目录/目录2: ./目录/目录2/目录3
./目录/目录2/目录3~目录列表: [ 'text3.txt' ]
./目录/目录2/目录3: ./目录/目录2/目录3/text3.txt
index10

node 的事件机制

触发事件的形式

其中有事件循环机制

nodejs入门基础(复习)_第18张图片

也可以用events模块自定义事件

定义与触发事件
let events =require('events')

//创建事件对象
let eventLog=new events.EventEmitter();
eventLog.on('lcMkDir',()=>{//触发时执行的函数
    console.log('lcMkDir','触发')
})

//触发事件
eventLog.emit('lcMkDir')

还可以携带多个参数

let events =require('events')

//创建事件对象
let eventLog=new events.EventEmitter();
eventLog.on('lcMkDir',()=>{//触发时执行的函数
    console.log('lcMkDir','触发')
})
eventLog.on('lcMkDir',(...args)=>{
    console.log('lcMkDir','带参数触发',args)
})
//触发事件
eventLog.emit('lcMkDir',{
    data:'msg'
},666)

image-20200727141335086

Buffer二进制数据缓冲区操作

node的读取流都是二进制data,默认的我们需要buffer缓冲区操作

//创建buffer,buffer.from()
let b1=Buffer.from('10')
console.log(b1)
console.log(b1.toString())

image-20200727142017899

//初始化缓冲区
let b2=Buffer.alloc(10);//创建大小为10字节的缓冲区
console.log(b2);//重置为0的缓冲区
let b3=Buffer.allocUnsafe(10);//创建大小为10字节的缓冲区但是不重置
console.log(b3)

image-20200727142304581

node的多进程

主要使用child_process模块

exec

child_process.exec(command[, options], callback)

//index1.js
console.log('进程:'+process.argv[2]+'执行')
//main1.js
const child_process=require("child_process")
for(var i=0;i<3;i++){
    //分别开启新进程去执行index1.js
    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)
        }const child_process=require("child_process")
for(var i=0;i<3;i++){
    //分别开启新进程去执行index1.js
    var workerProcess=child_process.exec('node index1.js '+i,function(err,stdout,stderr){
        if(err){
            console.log(err)
        }else{
            //stdout拿到子进程输出结果
            //stderr拿到子进程错误信息
            console.log('stdout',stdout)
            console.log('stderr',stderr)
        }
    })
    workerProcess.on('exit',(code)=>{
        console.log('退出'+code)
    })
}
    })
}

nodejs入门基础(复习)_第19张图片

spawn

child_process.spawn(command[, args][, options])

const child_process=require("child_process")
for(var i=0;i<3;i++){
    //分别开启新进程去执行index1.js
    var workerProcess=child_process.spawn('node',['./index1.js',i])
    workerProcess.on('close',(code)=>{
        console.log('退出'+code)
    })
    workerProcess.stdout.on('data',(data)=>{
        console.log(data.toString())
    })
    workerProcess.stderr.on('data',(err)=>{
        console.log(err)
    })
}

nodejs入门基础(复习)_第20张图片

另外进程通信可以使用

主进程

workerProcess.stdin.write(i + '');

子进程

process.stdin.on('data', function(data){})
fork

fork('./son.js')相当于 spawn('node', ['./son.js'])

const child_process=require("child_process")
for(var i=0;i<3;i++){
    //分别开启新进程去执行index1.js
    var workerProcess=child_process.fork('./index1.js',[i])
    workerProcess.on('close',(code)=>{
        console.log('退出'+code)
    })

}

nodejs入门基础(复习)_第21张图片

fork的线程通信更简单些

主线程

worker_process.send(i); //send-'message'

子线

process.on('message', function(m){})

path路径

先说一下和路径有关的全局变量

//node的全局变量
console.log(__dirname)//目录路径,D:\准备\老陈安排\nodejs基础\demo07
console.log(__filename)//文件路径,D:\准备\老陈安排\nodejs基础\demo07\index1.js

然后看一下path模块的操作

//node的全局变量
console.log(__dirname)//目录路径,D:\准备\老陈安排\nodejs基础\demo07
console.log(__filename)//文件路径,D:\准备\老陈安排\nodejs基础\demo07\index1.js

let path=require('path')
console.log(path.extname('./index1.js'))//获得扩展名,.js

console.log(path.basename(__filename))
console.log(path.basename('D:\\准备\\老陈安排\\nodejs基础\\demo07\\index1.js'))//获得文件名

console.log(path.dirname(__filename))//获取目录名称

console.log(path.normalize('D:/准备/老陈安排\\nodejs基础'))//转化成规范常用写法

console.log(__dirname+'/index1.js',path.join(__dirname,'index1.js'))//路径拼接

console.log(path.resolve('index1.js'))//路径解析

join和resolve的区别就是https://www.cnblogs.com/moqiutao/p/8523955.html

join是单纯的用/来拼接字符串,resolve则会从工作根目录解析出绝对路径

网络通信原理

协议:计算机之间使用协议进行通信,常用的有IP、TCP、HTTP、POP3、SMTP等

协议栈:协议的分层,有两种模型:TCP/IP和OSI

协议的作用:对等层虚拟通信;层次间的无关性

协议的层次间无关性:对等层通信时,只利用较低层次提供的接口和服务,不需要了解底层的协议,层层向下传递;底层也只是使用高层出传来的参数和信息

https://blog.csdn.net/weixin_30363263/article/details/80808231

nodejs入门基础(复习)_第22张图片

nodejs入门基础(复习)_第23张图片

理解HTTP协议

http:超文本传输协议是属于应用层的基于TCP/CP通信协议的从www服务器传输超文本到本地浏览器的传输协议

请求需要再仔细去看看

nodejs的HTTP模块

let http = require('http')
let server =http.createServer();//创建服务器

server.on('request',(req,res)=>{
    console.log(req.url)
    res.write(req.url)
    res.end()
})

//监听端口
server.listen(8003,()=>{
    console.log('启动:','http://localhost:8003')
})

启动之后

nodejs入门基础(复习)_第24张图片

然后根据解析req传递的请求就可以对应接口返送不同的数据了

nodejs使用express

let express=require('express')
let app=express()//实例化服务器

app.use(express.static('./static'))//访问静态资源


app.listen(3002,()=>{//启动监听
    console.log('express:','http://127.0.0.1:3002')
})

访问static下静态资源

image-20200727172624757

nodejs入门基础(复习)_第25张图片

自定义接口呢

let express=require('express')
let app=express()//实例化服务器

app.use(express.static('./static'))//访问静态资源

//自定义接口
app.get('/hello',(req,res)=>{
    res.send('hello')
})
app.get('/list',(req,res)=>{
    res.json({
        data:[
            1,2,3
        ]
    })
})
app.listen(3002,()=>{//启动监听
    console.log('express:','http://127.0.0.1:3002')
})

nodejs入门基础(复习)_第26张图片

nodejs入门基础(复习)_第27张图片

你可能感兴趣的:(前端,nodejs)