美文网首页
Node.js初探(四)

Node.js初探(四)

作者: 喑宝儿 | 来源:发表于2021-06-16 20:33 被阅读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()函数

    • 可以在处理函数中调用 res.send(响应内容) 对当前请求进行响应

    • send()的响应内容可以是多种形式的

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

    • req.query:默认情况下,内容为{ }

    • 请求URL:'/user'
      完整URL:http://127.0.0.1:3000/user?uname=zs&age=18
      req.query:
      {
        "name": "zs",
        "age": "18"
      }
      

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

    • req.params:默认状态下,内容为{ }

    • 请求URL:'/user/:uname/:age/:fav'
      完整URL:http://127.0.0.1:3000/user/zs/18/lily
      req.params:
      {
          "uname": "zs",
          "age": "18",
          "fav": "lily"
      }
      
    3、使用express托管静态资源
    • app.use(express.static(要托管的资源的路径))
      app.use(express.static('./shopping'))
      
    • 托管多个静态资源目录:多次调用app.use(express.static(资源路径))

    • 访问静态资源时,express.static()会根据目录的添加顺序查找所需的文件

    4、挂载路径前缀(在访问静态资源时,必须加上路径的前缀才能访问得到)
    • app.use(路径前缀, express.static(要托管的资源的路径))
      app.use('/public', express.static('./shopping'))
      
    5、路由:映射关系

    (1)express中的路由

    • 路由:客户端的请求与服务器处理函数之间的映射关系(包括请求方式、请求URL、处理函数)

    (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
    

    相关文章

      网友评论

          本文标题:Node.js初探(四)

          本文链接:https://www.haomeiwen.com/subject/smvfyltx.html