回顾与思考:
1.JavaScript能在浏览器中能够执行,是因为,浏览器使用JavaScript解析引擎进行解析
Chrome浏览器:V8引擎、IE浏览器:chakra查克拉
2.JavaScript可以操作DOM和BOM是因为浏览器提供了对应的API接口(API函数)
3.运行环境:指代码正常运行所必须的环境。例:浏览器中的运行环境:浏览器提供API接口->js调用API接口->js引擎执行代码
补充:终端:操作系统中专门为开发人员设计的,用于人机交互的一种方式
运行指令:nodemon / node + 执行的文件名称
一、初识node.js
定义:一个基于V8引擎可以运行JavaScript的运行环境
node终端中的快捷键
- 使用方向键向上按钮,可以快速定位到上一次执行的命令
- tab,快速补全路径
- esc,快速清空当前已经输入的命令
- cls,可以清空终端
二、 fs文件模块
定义:node中用来操作文件的模块。提供了一系列的方法和属性,用来满足用户对文件的操作需求
1.fs.readFile(“路径”,“编码格式”,function(err,dataStr){}):用来读取指定文件中的内容
2.fs.wirteFile () : 用来向指定文件中写入内容
一、例整理成绩
const fs = require('fs')
fs.readFile("./files/成绩.txt",function(err,data){
if(err) console.log("读取失败"+ err);
// console.log("读取成功"+data);
// 1.先把成绩进行按照空格分割
let value = data.toString().split(" ")
// console.log(value);
// 2.循环分割后的数组,对每一项
const arrNew = []
value.forEach(element => {
arrNew.push(element.replace("=",":"))
});
// 3.将数组转化为字符串
const strnew = arrNew.join("\r\n")
// console.log(strnew);
// 调用fs.wirte()
fs.writeFile("./files/成绩-OK.txt",strnew,function(err,data){
if(err) console.log("填入失败"+ err);
console.log("填入成功");
})
})
三、 path路径模块
path模块:用来处理路径的模块,提供了一系列的方法和属性,用来满足用户对路径的处理
- path.join () 用来将多个路劲拼接成一个完整的路径字符串
const path = require("path")
const fs = require("fs")
// const pathStr = path.join("/a","/b/c","../","./d","e") //../会消除掉上一个字母\a\b\d\e
// console.log(pathStr);
// const pathStr2 = path.join(__dirname,"./files/1.txt") //_dirname当前文件所处的目录
// console.log(pathStr2);
fs.readFile(path.join(__dirname,"/files/成绩.txt"),function(err,dataStr){
if(err) return console.log(err.message);
console.log(dataStr.toString());
})
- path.basename() 方法,用来从路径字符串中将文件名解析出来
const path = require("path")
//设置存放路径
const fpath = "/a/b/c/index.html"
// 使用basepath将文件名提取出来
const fullname = path.basename(fpath)
console.log(fullname); //index.html
// 跟了第二个参数就会截取掉扩展名
const namewithoutExt = path.basename(fpath,".html")
console.log(namewithoutExt); //index
- path.extname() 获取路径中的文件扩展名
const path = require("path")
const fpath = "/a/b/c/index.html"
const fext = path.extname(fpath)
console.log(fext); //.html
综合时钟案例
四、 http模块
回顾:
1.什么是客户端和服务端?
在网络节点中用来消费资源的电脑叫做客户端;用来对外提供网络资源的电脑叫做服务器
2.服务器和普通电脑的区别在于,服务器上安装了web服务器软件(IIS,Apache)这些软件将普通的电脑变成一台web服务器
3.IP地址
IP地址就是互联网上每一台计算机的唯一地址(相当于手机号码),只要在知道对方的IP地址的前提下,才能与对应的电脑之间进行数据通信
IP地址的格式为点分十进制(a,b,c,d)的形式。a,b,c,d都是0~255之间的十进制整数(互联网中的每台web服务器都有自己的IP地址)
在开发期间,自己的电脑即是一台服务器(127.0.0.1)也是一个客户端
4.域名和域名服务器
域名:IP地址的字符型地址方案(直观方便记忆)
域名服务器:域名和IP地址是一一对应的关系,这份对应关系存放在域名服务器中,使用者只需要通过几号的域名就可以访问对应的服务器,对应的转换工作由域名服务器来实现,因此,域名服务器就是提供IP地址和域名之间的转换服务的服务器
注意:
a.单纯有IP地址,互联网中的电脑也是可以正常工作的,但是有了域名的加持,能让互联网中的世界变得更加方便
b.127.0.0.1 对应的域名就是 localhost
5.端口号(相当于门牌号)
每个web服务都对应这唯一的端口号。客户端发送来的网络请求,通过端口号,可以被准确的给对应的web服务进行处理
每个端口号不能同时被多个web服务器占用,在实际应用中,URL中80端口可以被省略默认就是80
http模块:是node.js官方提供的,用来创建web服务器的模块。通过http模块提供的http.createServer()方法,就能方便的把一台普通的电脑,变成一台web服务器,从而对外提供web服务
五、express模块
基本使用
- express.static() 挂载静态资源
- app.use 挂载组件
- const router = express.Router() //创建路由对象
- router.get() 路由模块
六.中间件
- 中间件:在当中间件的业务逻辑处理完毕之后,必须调用next函数, 表示把流转关系转交给下一个中间件或者路由
- 全局中间件:在客户端发送请求到达服务器时先通过全局中间件,再到路由阶段
- 多个全局中间件:app.use() ,app.use() 多次定义中间件即可,客户请求到达服务器时,会通过中间件的定义顺序一次进行执行
- 局部生效中间件:不使用app.use()定义的中间件就是局部中间件
- 多个局部中间件:app.get(‘/’, mz1,mz2 (req,res) => {res.send()}) 多引入即可也是按照顺序进行执行 也可以用数组的方式进行[mz1,mz2]
const express = require("express")
const app = express()
const mw = function(req,res,next){
console.log("这是一个中间件函数");
// 注意:在当中间件的业务逻辑处理完毕之后,必须调用next函数
// 表示把流转关系转交给下一个中间件或者路由
next()
}
const mw1 = function(req,res,next){
console.log("这是一个中间件函数");
// 注意:在当中间件的业务逻辑处理完毕之后,必须调用next函数
// 表示把流转关系转交给下一个中间件或者路由
next()
}
// 注册全局中间件
app.use(mw)
//局部中间件,只对这个路由起作用
app.get('/',mw1,(req,res)=>{
console.log("调用了这个路由");
res.send("home ape")
})
app.listen(80,()=>{
console.log("127.0.0.1");
})
全局中间件简化
// 注册全局中间件
app.use(function(req,res,next){
console.log("这是一个中间件函数");
// 注意:在当中间件的业务逻辑处理完毕之后,必须调用next函数
// 表示把流转关系转交给下一个中间件或者路由
next()
}
)
-
中间件的作用:
-
多个中间件之间共享同一份req和res基于这样的特性,可以在上游的中间件,统一为req和res对象添加和自定义属性和方法,供下游的中间件或者路由使用
-
中间件的使用注意事项:
- 1.一定在路由之前注册中间件
- 2.客户端发送过来的请求,可以连续调用多个中间件进行处理
- 3.执行完中间件,不能忘记调用next函数
- 4.为了防止代码逻辑混乱,调用next函数后不要再写额外的代码
- 5.连续调用多个中间件的时候,多个中间件之间,共享req,res对象
-
中间件的分类:
-
1.应用级别的中间件
- 绑定到app实例上的中间件(app.use,app.get)
-
2.路由级别的中间件
- 绑定到express.Router()实例上的中间件
-
3.错误级别的中间件(必须放在所有路由中间件之后)
-
专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
// 注册全局中间件
app.use(function(err,req,res,next){
console.log("发生了错误"+err.message); //在服务器打印错误的信息
// 向客户端发送错误信息
res.send("Error"+err.message)
})
- 4.express内置的中间件(4版本之后内置了3个常用的中间件)
- express.static 快速托管静态资源的内置中间件,例如(HTML,图片,CSS)
- express.json 解析JSON格式的请求体数据(有兼容性4.16版本后)
app.use(express.json())
- express.urlencoded解析URL- encoded格式的请求体数据(有兼容性4.16版本后)
app.use(express.urllencoded({extended:false})
app.use(express.json())
app.use(express.urlencoded({extended:false}))
app.get('/',(req,res)=>{
console.log(req.body);//如果没有废纸任何解析表单数据的中间件,req.body默认等于undefined
res.send("ok")
})
app.post('/',(req,res)=>{
console.log(req.body);
res.send('ok')
})
- 5.第三方的中间件
- 1.下载安装对应中间件 npm install body-parsr
- 2.引入require
- 3.注册使用app.use(parsr.urlencoded(extend : false))
扩展:express内置的express.urllencoded 中间件,就是基于body-parsr这个第三方中间件进一步封装出来的
- 6.自定义中间件
- 实现步骤:
- 定义中间件
- 监听req的data事件
监听req对象的data事件,获取客户端发送到服务器的数据,如果数据量比较庞大,把数据切割之后,分批发送到服务器,需要手动对数据进行拼接
- 监听req的end事件
- 使用querystring模块解析请求体数据
// 4.将字符串格式的请求体数据解析为对象格式,使用内置模块querystring
- 将解析出来的数据对象挂载为req.body
上游的中间件和下游的中间件及路由之间,共享同一份的req和res,因此可以将解析出来的数据,挂载为req的自定义属性,命名为req.body供下游使用 - 将自定义中间件封装为模块