[Day07 nodejs | 青训营笔记]

47 阅读6分钟

这是我参与「第五届青训营 」笔记创作活动的第7天

初识Node.js

javascript可以通过node.js做后端开发

如何在node执行js代码

先切换到文件所属的目录

node 文件名 即可执行

shift+右键 可以打开powershell

终端中的快捷键

↑ 可以切换到上一条命令

使用tab键,可以补全文件路径

使用esc键,可以快速清空当前输入的命令

输入cls, 可以清空终端

fs文件系统模块

fs.readFile()方法,用来读取指定文件中的内容

fs.readFile(path[,options],callback)

参数1:读取文件的存放路径

参数2:读取文件时候采用的编码格式一般指定utf-8

参数3:回调函数。拿到读取失败和成功的结果 err dataStr

fs.readFile(path,utf-8 ,function(dataStr,err)){

console.log(dataStr)

console.log(err)

}

可以通过err来判断读取成功与否。

fs.writeFile()方法,用来向指定的文件中写入内容

fs.writeFile(file,data,[options],callback)

参数1: 指定一个文件路径字符串,表示文件的存放路径

参数2:表示写入的内容

参数3:可选参数,表示以什么格式写入文件内容,默认是 utf-8

参数4:文件写入完成后的回调函数

使用fs模块来操作文件,需要先导入他

const fs = require('fs')

fs模块-路径动态拼接的问题

在使用fs模块操作文件时,如果提供的操作路径是以./或../开头的相对路径时,很容易出现路径动态拼接错误的问题

原因:代码在运行时,会以执行node 命令时所处的目录,动态拼接出被操作文件的完整路径

出现路径拼接错误的问题,是因为提供了./或../相对路径,如果要解决,直接提供一个完整的文件存放路径

__dirname 表示当前文件所处的目录

可以 __dirname + 相对路径

流式文件读取

  • 简单文件读取的方式会一次性读取文件内容到内存中,若文件较大,会占用过多内存影响系统性能,且读取速度慢
  • 大文件适合用流式文件读取,它会分多次将文件读取到内存中
var fs = require('fs')

// 创建一个可读流
var rs = fs.createReadStream('C:/Users/笔记.mp3')
// 创建一个可写流
var ws = fs.createWriteStream('a.mp3')

// 监听流的开启和关闭
// 这几个监听不是必须的
rs.once('open', function () {
  console.log('可读流打开了~~')
})

rs.once('close', function () {
  console.log('可读流关闭了~~')
  //数据读取完毕,关闭可写流
  ws.end()
})

ws.once('open', function () {
  console.log('可写流打开了~~')
})

ws.once('close', function () {
  console.log('可写流关闭了~~')
})

//要读取一个可读流中的数据,要为可读流绑定一个data事件,data事件绑定完毕自动开始读取数据
rs.on('data', function (data) {
  console.log(data)
  //将读取到的数据写入到可写流中
  ws.write(data)
})

简便方式:

var fs = require('fs')

var rs = fs.createReadStream('C:/Users/lilichao/Desktop/笔记.mp3')
var ws = fs.createWriteStream('b.mp3')

// pipe()可以将可读流中的内容,直接输出到可写流中
rs.pipe(ws)

流式文件写入

// 同步、异步、简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出
var fs = require('fs')

// 创建一个可写流
var ws = fs.createWriteStream('hello3.txt')

ws.once('open', function () {
  console.log('流打开了~~')
})

ws.once('close', function () {
  console.log('流关闭了~~')
})

// 通过ws向文件中输出内容
ws.write('通过可写流写入文件的内容')
ws.write('1')
ws.write('2')
ws.write('3')
ws.write('4')

// 关闭流
ws.end()

其它操作

验证路径是否存在:

  • fs.exists(path, callback)
  • fs.existsSync(path)

获取文件信息:

  • fs.stat(path, callback)
  • fs.stat(path)

删除文件:

  • fs.unlink(path, callback)
  • fs.unlinkSync(path)

列出文件:

  • fs.readdir(path[,options], callback)
  • fs.readdirSync(path[, options])

截断文件:

  • fs.truncate(path, len, callback)
  • fs.truncateSync(path, len)

建立目录:

  • fs.mkdir(path[, mode], callback)
  • fs.mkdirSync(path[, mode])

删除目录:

  • fs.rmdir(path, callback)
  • fs.rmdirSync(path)

重命名文件和目录:

  • fs.rename(oldPath, newPath, callback)
  • fs.renameSync(oldPath, newPath)

监视文件更改:

  • fs.watchFile(filename[, options], listener)

path路径模块

什么是path路径模块

用来处理路径的模块

引入方式

const path = require("path");

path.join(),用来将多个路径片段拼接成一个完整的路径字符串

path.(...path)

const pathStr = path.join('/a','/b/c','e');

路径拼接

const url=path.join(__dirname,'./file.txt')

path.basename(),用来从路径字符串中,将文件名解析出来

通过path.basename(),可以获取路径中的 最后一部分,经常获取路径中的文件名

var fullName= path.basename('/a/b/c/index.html')

console.log(fullName); //输出 index.html

var fullName= path.basename('/a/b/c/index.html','.html')

console.log(fullName); //输出 index

path.extname(),可以获取文件路径中的扩展名

console.log(path.extname('/a/b/c/index.html')) //输出 .html

时钟案例

导入需要的模块并创建正则表达式

const  fs  =  require('fs')
const path = require("path")
// 匹配<style></style>标签的正则
其中  \s 表示空白字符   \S表示非空白字符     *表示匹配任意次
const regStyle = /<style>[\s\S]* </style>/
// 匹配<script></script>标签的正则
const regScript = /<script>[\s\S]*</script>/

HTTP模块

http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块。

创建基本 Web 服务器

const http = require('http')

// 创建 web 服务器实例
const server = http.createServer()

// 为服务器实例绑定 request 事件,监听客户端的请求
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)

  // 设置 Content-Type 响应头,解决中文乱码的问题
  res.setHeader('Content-Type', 'text/html; charset=utf-8')
  // 向客户端响应内容
  res.end(str)
})

server.listen(8080, function () {
  console.log('server running at http://127.0.0.1:8080')
})

简易路由

const http = require('http')
const server = http.createServer()

server.on('request', (req, res) => {
    const url = req.url
    // 设置默认的响应内容为 404 Not found
    let content = '<h1>404 Not found!</h1>'
    // 判断用户请求的是否为 / 或 /index.html 首页
    // 判断用户请求的是否为 /about.html 关于页面
    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 running at http://127.0.0.1')
})

Express 初体验

创建服务器,监听客户端请求,并返回内容:

const express = require('express')
// 创建 web 服务器
const app = express()

// 监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get('/user', (req, res) => {
  res.send({ name: 'zs', age: 20, gender: '男' })
})
app.post('/user', (req, res) => {
  res.send('请求成功')
})

app.get('/', (req, res) => {
  // 通过 req.query 可以获取到客户端发送过来的查询参数
  console.log(req.query)
  res.send(req.query)
})

// 这里的 :id 是一个动态的参数
app.get('/user/:ids/:username', (req, res) => {
  // req.params 是动态匹配到的 URL 参数,默认是一个空对象
  console.log(req.params)
  res.send(req.params)
})

app.listen(80, () => {
  console.log('express server running at http://127.0.0.1')
})

应用级别中间件

index.js 服务器启动文件

const express = require("express")
const app = express()
const HomeRouter = require("./router3/HomeRouter")
const LoginRouter = require("./router3/LoginRouter")

// 应用级别中间件的效果是   每次运行的时候都会执行他
//应用级别  先匹配 应用级别中间件,再匹配路由
app.use(function (req,res,next){
  console.log("验证token");
  next()
})
//应用级别
app.use("/home",HomeRouter)
app.use("/login",LoginRouter)

//错误级别中间件 放最下面 兜底作用
app.use((req,res)=>{
  res.status(404).send("丢了")
})

app.listen(3000,()=>{
  console.log("服务器运行起来了")
})
//还有内置中间件 和  第三方中间件

HomeRouter

const express = require("express")

const router = express.Router()

router.get("/",(req,res)=>{
    res.send("home")
})

router.get("/swiper",(req,res)=>{
    res.send("home-swiper")
})

router.get("/slide",(req,res)=>{
    res.send("home-slide")
})

// 导出
module.exports = router

LoginRouter

const express = require("express")

const router = express.Router()

router.get("/",(req,res)=>{
    res.send("login")
})

module.exports = router

get,post请求获取请求参数

const express = require("express")
const app = express()
const HomeRouter = require("./router3/HomeRouter")
const LoginRouter = require("./router3/LoginRouter")

//配置解析post参数的-不用下载第三方,内置。  必须写到应用级中间件前面
app.use(express.urlencoded({entended:false}))

// 应用级别中间件的效果是   每次运行的时候都会执行他
//应用级别  先匹配 应用级别中间件,再匹配路由
app.use(function (req,res,next){
    console.log("验证token");
    next()
})
//应用级别
app.use("/home",HomeRouter)
app.use("/login",LoginRouter)

//错误级别中间件 放最下面 兜底作用
app.use((req,res)=>{
    res.status(404).send("丢了")
})

app.listen(3000,()=>{
    console.log("服务器运行起来了")
})
//还有内置中间件 和  第三方中间件
const express = require("express")

const router = express.Router()

//路由级别-> 响应前端的 get请求
router.get("/",(req,res)=>{
    console.log(req.query)
    res.send("login-success")
})

//路由级别-> 响应前端的 post 请求
router.post("/",(req,res)=>{
    console.log(req.body)//必须配置中间件
    res.send({ok:1})
})

//路由级别->响应前端的 put,delete 请求


module.exports = router