Node.js初探(四)

2021-06-16  本文已影响0人  喑宝儿
1、初识express:

与http模块类似,对http进一步封装,专门用来创建web服务器

服务器:web网站服务器、API接口服务器

2、使用express创建最基本的服务器

(1)安装:npm i express@4.17.1

(2)创建简单的服务器以及请求

可以通过get和post进行请求处理

const express = require('express')

const app = express()
// 监听get请求
app.get('请求URL', function(req, res) {/* 处理函数 */})
// 监听post请求
app.post('请求URL', function(req, res) {/* 处理函数 */})

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

(3)send()函数

(4)获取URL中携带的查询参数:

(5)URL中的动态参数(可有多个动态参数):

3、使用express托管静态资源
4、挂载路径前缀(在访问静态资源时,必须加上路径的前缀才能访问得到)
5、路由:映射关系

(1)express中的路由

(2)路由的匹配过程

  • 按照定义的先后顺序进行匹配

  • 请求类型和请求URL地址需要同时匹配成功,才会调用对应的处理函数

6、挂载路由
// app express对象
app.get('/', function(req, res) { res.send('111') })
app.post('/', function(req, res) { res.send('222') })

一般路由不建议直接挂载

7、模块化路由
/** router.js */
// 1、导入express
const express = require('express')
// 2、创建路由对象
const router = express.Router()
// 3、挂载具体的路由
router.get('/user/list', (req, res) => {
    res.send('get user list')
})
router.post('/user/add', (req, res) => {
    res.send('add user list')
})
// 4、向外导出路由对象
module.exports = router
/** 使用test.js */
const express = require('express')
const app = express()
// 1、导入路由模块
const router = require('./03.router')
// 2、注册路由模块
app.use(router)
app.listen(80, () => {
    console.log('http://127.0.0.1');
})

app.use():专门用来注册中间件的

app.use(访问前缀, router):也可以为路由模块挂载访问前缀,在访问路由时都需要加上

8、中间件:用户请求到路由匹配中间的过程(对请求进行预处理)

(1)express中间件的格式

本质是一个函数,在函数的形参列表中,必须包含next参数,next必须是最后一个参数

(2)next函数的作用

实现多个中间件连续调用,表示把流转关系转交给下一个中间件或路由

(3)定义中间件函数

const mw = function(req, res, next) {
    console.log('这是一个中间件函数')
  // 将流转关系,转交给下一个中间件函数
    next()
}

(4)注册中间件

全局生效的中间件:app.use(中间件函数)

// 将mw注册为全局生效的中间件,中间件都要在路由的前面进行定义,发送请求先进入中间件
app.use(mw)

中间件的作用:

多个中间件之间,共享一根req和res,基于这样的特性,可以在上游的中间件中,统一为req或者res对象添加自定义的属性或方法,供下游的中间件或路由进行使用

app.use((req, res, next) => {
  req.startTime = Date.now()
  next()
})

app.get('/', (req, res) => {
  res.send('Home' + req.startTime)
})

app.get('/user', (req, res) => {
  res.send('User' + req.startTime)
})

定义多个全局中间件:

可以使用app.use()连续定义多个全局中间件,客户端请求到达服务器之后,会按照中间定义的先后顺序依次进行调用

app.use((req, res, next) => {
  console.log('第一个')
  next()
})

app.use((req, res, next) => {
  console.log('第二个')
  next()
})

局部生效的中间件:不使用app.use()定义的中间件

// 只会在/路由中才会打印'局部中间件',因为只给/路由注册
const mw = function(req, res, next) {
    console.log('局部中间件')
    next()
}

app.get('/', mw, (req, res) => {
  res.send('Home')
})

app.get('/user', (req, res) => {
  res.send('User')
})

定义多个局部中间件:

// 下面两个是等价的
app.get('/', mw1, mw2, (req, res) => { res.send('Page') })
app.get('/', (mw1, mw2), (req, res) => { res.send('Page') })
9、中间件的注意事项

(1)一定要在路由之前注册中间件

(2)客户端发过来的请求,可以连续调用多跟中间件进行处理

(3)执行完中间件的业务代码之后,不要忘记调用next()函数

(4)为了防止代码逻辑混乱,调用next()函数之后不要再写额外的代码

(5)连续调用多个中间件时,多个中间件之间,共享req和res对象

10、中间件的分类

(1)应用级别:app.use()/app.get()/app.post(),直接绑定到app实例上的中间件

(2)路由级别:绑定到express.Router()实例上的中间件(和应用级别用法相同)

(3)错误级别:

捕获整个项目中发生的异常错误,防止项目异常崩溃的问题

错误级别的中间件一定要写在路由之后

格式:处理函数中,必须有4个形参,顺序从前到后,分别是(err, req, res, next)

const express = require('express')
const app = express()

// 1、定义路由
app.get('/', (req, res) => {
    throw new Error('服务器内部发生了错误!')
    res.send('Home page')
})

// 2、定义错误级别的中间件
app.use((err, req, res, next) => {  // 错误级别中间件
    console.log('Error:' + err.message);  // 1、在服务端打印错误信息
    res.send('Error:' + err.message)  // 2、向客户端返回错误信息
})

app.listen(80, () => {
    console.log('http://127.0.0.1');
})
11、Express内置的中间件

(1)express.static:静态托管资源

(2)express.json:解析JSON格式的请求体数据

(3)express.urlencoded:解析URL-encoded格式的请求体数据

// 解析JSON
app.use(express.json())

// 解析urlencoded
app.use(express.urlencoded({ extended: false }))
12、第三方中间件body-parser(解析请求体数据)

(1)安装:npm i body-parser

(2)使用require导入文件

(3)调用app.use()注册并使用中间件

const express = require('express')
const app = express()

const parser = require('body-parser')
app.use(parser.urlencoded({ extended: false }))

app.post('/', (req, res) => {
    console.log(req.body);
    res.send('ok')
})

app.listen(80, () => {
    console.log('http://127.0.0.1');
})

内置请求体解析中间件就是对body-parser中间件的封装

13、自定义中间件:模拟express.urlencoded类似功能

(1)定义中间件

(2)监听req的data操作:查看是否有数据被提交

(3)监听req的end事件:数据已经发送完毕,服务端已经接收到了数据

(4)使用querystring模块解析请求体数据:

(5)将解析出来的数据对象挂载为req.body

(6)将自定义的中间件封装为模块

完整文件

const express = require('express')
const app = express()

const bodyParse = require('./bodyParse')

app.use(bodyParse)

app.post('/user', (req, res) => {
    res.send(req.body)
})

app.listen(80, () => {
    console.log('http://127.0.0.1');
})

可以将功能单独封装(// 步骤(6)),然后再注册路由中间件(bodyParse.js)

const qs = require('querystring')

// 步骤(1)
const bodyPaser = (req, res, next) => {
    var str = ''
    // 步骤(2)
    req.on('data', chunk => {
        str += chunk
    })
    // 步骤(3)
    req.on('end', () => {
        // 步骤(4)(5)
        req.body = qs.parse(str)
        next()
    })
}

module.exports = bodyPaser
上一篇下一篇

猜你喜欢

热点阅读