Node学习笔记
初识Node
什么是Node.js?
Node.js是一个基于Chrome V8引擎的JS运行环境。
为什么JS可以操作DOM、BOM
每个浏览器都内置了DOM、BOM这样的API函数。因此,浏览器中的JS才可以调用它们。
浏览器中的JS运行环境
运行环境是指代码正常运行所需要的必要环境
Chrome浏览器运行环境
V8引擎(负责解析和执行JS代码)
内置API(由运行环境提供的特殊接口,只能在所述的运行环境中被调用):
DOM BOM Canvas XMLHttpRequest JS内置对象…
Node.js中的Js运行环境
V8引擎(负责解析和执行JS代码)
内置API(由运行环境提供的特殊接口,只能在所述的运行环境中被调用):
fs path http JS内置对象 querystring etc…
注意:
-
浏览器是JS的前端运行环境
-
Node.js是JS的后端运行环境
-
Node.js中无法调用DOM BOM等浏览器内置API
js做后端开放需要借助Node.js运行环境
Node安装
官网:https://nodejs.org/zh-cn/
LTS为长期稳定版,推荐安装
Current为新特性尝鲜版,但是可能存在隐藏的Bug或安全性漏洞,因此不推荐在企业级项目中使用
- 查看已安装的Node.js版本号
只需打开终端(win+R,输入cmd后回车),在终端中输入命令node -v,按下回车即可查看已安装的版本号
在Node.js环境中执行JS代码
-
打开终端(也可以右击想要执行的文件,点击在中端中打开)
-
输入node要执行的js文件的路径
终端中的快捷键
-
↑ 可以快速定位到上一次执行的命令
-
tab 能够快速补全路径
-
esc 能够快速清空当前已输入命令
-
cls 可以清空终端
fs文件系统模块
fs模块是Node.js官方提供的、用来操作文件 的模块,它提供了一系列的方法和熟悉,用来满足用户对文件的操作需求。
例如:
fs.readFile()
用来读取指定文件中的内容
fs.writeFile()
用来向指定文件中写入内容
导入方法
const fs = require('fs')
读取文件内容
- fs.readFile()的语法格式
const fs = require('fs')
fs.readFile(path[, options], callback)//被中括号包起来的为可选参数项目
参数1:必选参数,字符串,表示文件的路径
参数2:可选参数,表示以什么编码格式来读取文件
参数3:必选参数,文件读取完成后,通过回调函数拿到读取的结果
- 示例:
以utf8的编码格式,读取指定文件的内容,并打印err和dataStr的值:
readfile.js代码
const fs = require('fs')
fs.readFile('./files/1.txt','utf8',function(err,dataStr){
//如果读取成功,则err值为null;失败则值为错误对象
//如果读取成功,dataStr为成功的结果;失败则为undefined
console.log(err)
console.log('----')
console.log(dataStr)
})
files文件夹下1.txt的内容
111
执行 node readfile.js
修改readfile.js代码中的路径
再次执行,则结果为:
判读文件读取是否成功
const fs = require('fs')
fs.readFile('./files/1.txt','utf8',function(err,dataStr){
if(err){
return console.log('读取文件失败' + err.message)
}
console.log('读取文件成功' + dataStr)
})
向指定文件中写入内容
- fs.writeFile()的语法格式
const fs = require('fs')
fs.writeFile(file, data[, options], callback)//被中括号包起来的为可选参数项目
参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径
参数2:必选参数,表示要写入的内容
参数3:可选参数,表示以什么编码格式来写入文件,默认utf8
参数4:必选参数,文件写入完成后的回调函数
- 示例:
向指定的文件路径中,写入文件内容:
writeFile.js文件中的内容
const fs = require('fs')
fs.writeFile('./files/2.txt','Hello Node.js!',function(err){
//如果文件写入成功,则err的值为null
//如果文件写入失败,则err的值等于一个错误对象
console.log(err)
})
终端中执行 node writeFile.js
且files文件夹下会多一个2.txt文件,且里面的内容为Hello Node.js!
判断文件写入是否成功
const fs = require('fs')
fs.writeFile('./files/3.txt','Hello abc!',function(err){
//如果文件写入成功,则err的值为null
//如果文件写入失败,则err的值等于一个错误对象
// console.log(err)
if(err){
return console.log('文件写入失败' + err.message)
}
console.log('文件写入成功')
})
EX 考试成绩整理
核心实现步骤:
- 导入需要的fs文件系统模块
- 使用
fs.readFile()
,读取素材目录下的成绩.txt文件 - 判断文件是否读取失败
- 文件读取成功后,处理成绩数据
- 将处理完成的成绩数据,调用
fs.writeFile()
方法,写入到新文件成绩-ok.txt中
成绩.txt中的内容
小红=99 小白=100 小黄=70 小黑=66 小绿=88
具体操作
const fs = require('fs')
fs.readFile('./files/成绩.txt', 'utf8', function(err,dataStr){
if(err){
return console.log('读取文件失败' + err.message)
}
//先把成绩按照空格进行分割
const arrOld = dataStr.split(' ')
//循环分割后的数组,对每一项数据进行字符串的替换操作
const arrNew = [];
arrOld.forEach(item => {
arrNew.push(item.replace('=',':'))
})
//把新数组的每一项,进行合并,得到一个新的字符串
const res = arrNew.join('\r\n')
//把处理完毕的数据写入新文件中
fs.writeFile('./files/成绩-ok.txt', res, function(err){
if(err){
return console.log('文件写入失败' + err.message)
}
console.log('文件写入成功')
})
})
在执行终端上运行后,输出文件写入成功,并且files文件夹下多出一个成绩-ok.txt
fs模块路径动态拼接问题
在使用fs模块操作文件时,如果提供的操作路径是以./或…/开头的相对路径,很容易出现路径动态拼接错误的问题。
原因:代码在运行时,会以执行node命令时所处的目录,动态拼接出被操作文件的完整路径
解决方法:直接提供完整的路径(移植性差,不利于维护)
新的解决方法:借助__dirname
__dirname
表示当前文件所处的目录
const fs = require('fs')
fs.readFile(__dirname + '/files/1.txt','utf8',function(err,dataStr){
if(err){
return console.log('读取文件失败' + err.message)
}
console.log('读取文件成功' + dataStr)
})
path路径模块
path模块是Node.js官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径 的处理需求。
例如:
path.join()
用来将多个路径片段拼接成一个完整的路径字符串
path.basename()
用来从路径字符串中,将文件名解析出来
path.extname()
获取路径中的文件扩展名
导入方法
const path = require('path')
路径拼接
path.join()
语法格式
path.join([...path])
参数解读:
-
…path 路径片段的序列
-
返回值:
- 示例:
const path = require('path')
const pathStr = path.join('/a', '/b/c', '../', './d', 'e')
//注意../会抵消前面的路径
console.log(pathStr) //输出 \a\b\d\e
const pathStr2 = path.join(__dirname, './files/1.txt')
console.log(pathStr2)
注意:
今后凡是涉及到路径拼接的操作,都要使用path.join()
方法进行处理,不要直接使用+字符串的拼接。
获取路径中的文件名
path.basename()
的语法格式
path.basename(path[, ext])
参数解读:
-
…path 必选参数,表示一个路径的字符串
-
ext 可选参数,表示文件扩展名
-
返回值: 表示路径中的最后一部分
- 示例:
const path = require('path')
const fpath = '/a/b/c/index.html'
// const fullName = path.basename(fpath)
// console.log(fullName) //index.html
const nameWithoutExt = path.basename(fpath,'.html')
console.log(nameWithoutExt) //index
获取路径中的文件扩展名
path.extname()
的语法格式
path.extname(path)
- 示例:
const path = require('path')
const fpath = '/a/b/c/index.html'
const fext = path.extname(fpath)
console.log(fext) //.html
EX 时钟案例
将index,html文件拆分成三个文件,分别是:index.css index.js index.html,并且将拆分出来的三个文件,存放到clock目录中
案例实现步骤:
- 创建两个正则表达式,分别用来匹配
<style><script>
标签 - 使用fs模块,读取需要被处理的HTML文件
- 自定义resolveCSS方法,来写入index.css样式文件
- 自定义resolveJS方法,来写入index.js文件
- 自定义resolveHTML方法,来写入index.html文件
具体实现:
!!注意一定要提前创建clock文件夹
const fs = require('fs')
const path = require('path')
//定义正则表达式,分别匹配<sc> </style>和 <script> </script>标签
const regStyle = /<style>[\s\S]*<\/style>/
const regScript = /<script>[\s\S]*<\/script>/
//调用fs.readFile方法读取文件
fs.readFile(path.join(__dirname,'./files/index.html'),'utf8',function(err,dataStr){
if(err){
return console.log('读取文件失败' + err.message)
}
//调用对应的三个方法,分别拆解出css,js,html文件
resolveCSS(dataStr)
resolveJS(dataStr)
resolveHTML(dataStr)
})
//定义处理CSS样式的方法
function resolveCSS(htmlStr){
const r1 = regStyle.exec(htmlStr)
//将提取出来的样式字符串,进行字符串的replace操作
const newCSS = r1[0].replace('<style>','').replace('</style>','')
fs.writeFile(path.join(__dirname,'./clock/index.css'), newCSS, function(err){
if(err){
return console.log('写入CSS失败' + err.message)
}
console.log('写入CSS成功')
})
}
//定义处理JS样式的方法
function resolveJS(htmlStr){
const r2 = regScript.exec(htmlStr)
//将提取出来的样式字符串,进行字符串的replace操作
const newJS = r2[0].replace('<script>','').replace('</script>','')
fs.writeFile(path.join(__dirname,'./clock/index.js'), newJS, function(err){
if(err){
return console.log('写入JS失败' + err.message)
}
console.log('写入JS成功')
})
}
//处理html文件
function resolveHTML(htmlStr){
const newHTML = htmlStr.replace(regStyle,'<link rel="stylesheet" href = "./index.css"/>').replace(regScript,'<script src="./index.js"></script>')
fs.writeFile(path.join(__dirname,'./clock/index.html'),newHTML,function(err){
if(err){
return console.log('写入HTML失败' + err.message)
}
console.log('写入HTML成功')
})
}
注意事项:
fs.writeFile()
方法只能用来创建文件,不能用来创建路径- 重复调用
fs.writeFile()
写入同一个文件,新写入的内容会覆盖之前的就内容
http模块
回顾:客户端和服务器的概念
在网络节点中,负责消费资源的电脑,叫做客户端;负责对外提供网络资源的电脑,叫做服务器。
http模块是Node.js提供的,用来创建web服务器的模块。通过http模块提供的http.createServer()
方法,就能方便的把一台普通电脑,变成一台web服务器,从而对外提供web资源服务。
导入方法
const http = require('http')
服务器相关概念
- IP地址:
IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6)
-
互联网中每台Web服务器,都有自己的IP地址。(可尝试在终端中 运行 ping www.baidu.com)
-
开发期间,自己的电脑即是一台服务器,也是一个客户端。为了方便测试,可以在自己的浏览器总输入127.0.0.1这个IP地址,就可以把自己的电脑当作一台服务器进行访问了。
- 域名和域名服务器
由于IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和IP地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址数串。
IP地址和域名是一一对应的,这份域名地址的信息存放在一个叫域名服务器(DNS,Domain name server)的主机内,使用者只需了解易记的域名地址,其对应转换工作就留给了域名服务器。域名服务器就是提供IP地址和域名之间的转换服务的服务器。
注意:
- 在开发测试期间,127.0.0.1对应的域名是localhost,它们都代表我们自己的这台电脑
- 端口号
所谓的端口,就好像是门牌号一样,客户端可以通过ip地址找到对应的服务器端,但是服务器端是有很多端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器。为了对端口进行区分,将每个端口进行了编号,这就是端口号
注意:
-
每个端口号不能同时被多个web服务占用
-
在实际应用中,URL中的80端口可以被忽略
创建最基本的web服务器
创建的基本步骤
- 导入http模块
- 创建web服务器实例
const server = http.createServer()
- 为服务器实例绑定request事件(
server.on()
),监听客户端的请求 - 启动服务器(
server.listen(端口号,callback)
)
(Ctrl+C可以停止服务)
具体代码实现:
//导入http模块
const http = require('http')
//创建web服务器实例
const server = http.createServer()
//为服务器实例绑定request事件,监听客户端的请求
server.on('request',function(req, res){
console.log('Someone visit our web server')
})
//启动服务器
server.listen(8080,function(){
console.log('server is running at http://127.0.0.1:8080')
})
req请求对象和res响应对象
req请求对象
只要服务器接收到了客户端的请求,就会调用通过server.on()
为服务器绑定的request事件处理函数。
如果想要在事件处理函数中,访问与客户端相关的数据或属性。
req.url
是客户端请求的URL地址
req.method
是客户端的method请求类型
具体代码:
const http = require('http')
const server = http.createServer()
//req是对象,包含了与客户端相关的数据和属性
server.on('request',function(req, res){
const url = req.url
const method = req.method
const str = `Your request url is ${url}, and request method is ${method}`
console.log(str)
})
//启动服务器
server.listen(80,function(){
console.log('server is running at http://127.0.0.1')
})
在终端中执行,并打开页面,会显示前两行。如果我们在127.0.0.1后加上/index.html,则会出现下图最后一行的输出
res响应对象
在服务器的request事件处理函数中,如果想访问与服务器相关的数据或属性,可以使用如下的方式
const http = require('http')
const server = http.createServer()
//req是对象,包含了与客户端相关的数据和属性
server.on('request',function(req, res){
const url = req.url
const method = req.method
const str = `Your request url is ${url}, and request method is ${method}`
console.log(str)
//调用res.end(),向客户端发送指定的内容,并结束这次请求的处理过程
res.end(str)
})
//启动服务器
server.listen(80,function(){
console.log('server is running at http://127.0.0.1')
})
解决中文乱码
如果我们的代码如下:
const http = require('http')
const server = http.createServer()
server.on('request',function(req, res){
const url = req.url
const method = req.method
const str = `您请求的URL地址是 ${url}, 请求的method类型是 ${method}`
console.log(str)
res.end(str)
})
//启动服务器
server.listen(80,function(){
console.log('server is running at http://127.0.0.1')
})
打开页面之后,中文部分会出现乱码
调用res.setHeader()
方法,设置Content-Type响应头,解决中文乱码问题
const http = require('http')
const server = http.createServer()
server.on('request',function(req, res){
const url = req.url
const method = req.method
const str = `您请求的URL地址是 ${url}, 请求的method类型是 ${method}`
//调用res.setHeader()方法,设置Content-Type响应头,解决中文乱码问题
res.setHeader('Content-Type','text/html; charset=utf-8')
res.end(str)
})
//启动服务器
server.listen(80,function(){
console.log('server is running at http://127.0.0.1')
})
再次打开页面
根据不同URL响应不同的html内容
核心实现步骤:
- 获取请求的url地址
- 设置默认的响应内容为404 Not found
- 判断用户请求的是否为/或/index.html首页
- 判断用户请求的是否为/about.html关于页面
- 设置Content-Type响应头,防止中文乱码
- 使用
res.end()
把内容响应给客户端
具体代码实现
const http = require('http')
const server = http.createServer()
server.on('request',(req,res)=>{
const url = req.url
let content = '404 Not found!'
if(url === '/' || url === '/index.html' ){
content = '<h1>首页</h1>'
}else if(url === '/about.html'){
content = '<h1>关于页面</h1>'
}
res.setHeader('Content-Type','text/html; charset=utf-8')
res.end(content)
})
server.listen(80,()=>{
console.log('server is running at http://127.0.0.1')
})
EX 实现clock时钟的web服务器
核心思路:
把文件的实际存放路径,作为每个资源的请求url地址
实现步骤:
- 导入需要的模块
- 创建基本的web服务器
- 将资源的请求url地址映射为文件的存放路径
- 读取文件的内容并响应给客户端
- 优化资源的请求路径
const http = require('http')
const fs = require('fs')
const path = require('path')
const server = http.createServer()
server.on('request',(req,res)=>{
//获取到客户端请求的url地址
// /clock/index.html
const url = req.url
//把请求的url地址,映射为本地文件的存放路径
//如果用户写的 路径不完整,帮用户自动补一下/clock
let fpath = ''
if(url === '/'){
fpath = path.join(__dirname, '/clock/index.html')
}else{
fpath = path.join(__dirname,'/clock', url)
}
//读取文件的内容并响应给客户端
fs.readFile(fpath, 'utf8', (err,dataStr)=>{
if(err) return res.end('404 Not found')
res.end(dataStr)
})
})
//启动服务器
server.listen(80,function(){
console.log('server is running at http://127.0.0.1')
})