Node3+中间件

106 阅读4分钟

1.get方式

完善ajax请求

xhr.open("GET", "/api/goods/list?current=1&pageSize=12")

    function myAjax1() {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "/api/goods/list?current=1&pageSize=12");
    xhr.onload = function () {
        console.log(JSON.parse(xhr.responseText));
    };
    xhr.send();
}

myAjax1();
 *  当前函数会接收到一个参数 goodsId
 *  我们拿到之后, 应该去数据库查到对应的 商品, 然后将商品详情返回给前端
 *
 *  在当前服务器中, 我们使用的是 express 框架, 所以我们可以借助框架, 少做很多事
 *
 *  比如当前请求的参数, expres 帮我们放在 req.query 中
 * 
 *      注意: 只有 get 方式 可以通过 req.query 拿到
 
在controller中的goods文件夹中拿到参数返回前端
    exports.getGoodsList = (req, res) => {
    // 1. 拿到参数
    const query = req.query;
    console.log(query);

    // 2. 去数据库查询数据

    // 3. 将查询到的数据, 返回给前端
    res.send({
        code: 1,
        msg: "/goods/list 请求成功",
        tips: `您当前要请求的是第 ${query.current} 页的数据, 一共 ${query.pagesize} 条`,
    });
};

2,post方式

完善ajax请求

xhr.send('id=20040216')

    function myAjax2() {
    const xhr = new XMLHttpRequest()
    xhr.open('POST', '/api/users/info')
    xhr.onload = function () {
        console.log(JSON.parse(xhr.responseText))
    }
    xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
    xhr.send('id=20040216')
}
myAjax2()
 *  get 请求的时候 参数是拼接在 路径后的, 所以 express 能够直接帮助我们解析出来
 *
 *  但是 post 的方式, 参数是在 请求体中的, 因为 请求体的东西比较多, 所以 express 不会帮我们解析
 *
 *  所以就只能我们自己来写代码接收参数了~
 *
 *  如果不想自己写, 就能找人帮你写, 现在恰好有一个人写好了一个接收参数的代码, 上传到 npm 仓库中
 *
 *  我们就可以把他当成一个第三方模块, 下载 导入 使用
 *
 *  这个第三方包的名字就叫 body-parser, 这个第三方包比较特殊, 是 express 所依赖的第三方包
 *  所以我们没有下载但是 node_modules 也有
 *
 *  但是! express 在每年都会说一句 请不要使用因为明年我就不依赖了, 需要你自己下载
在controller中的users文件夹中拿到参数返回前端
    exports.postUsersInfo = (req, res) => {
    // console.log(req.query)  // {}

    // 1. 拿到参数
    const myBody = req.body;

    // 2. 去数据库查询对应的用户详情

    // 3. 将查询到的数据, 返回给前端
    res.send({
        code: 1,
        msg: "/users/info 请求成功",
        tips: `您请求的是 ID ${myBody.id} 的用户`,
    });
};
服务器js文件中引入
 *  在 express 框架中
 *      如果是 get 请求, 那么参数会被 express 框架解析到 req.query 中
 *      如果是 post 请求, 那么参数不会被 express 框架解析
 *          我们需要利用一个第三方包帮我们去解析 (body-parser)
 *          这个第三方包会将我们的参数解析到 req.body 中
//导入第三方模块
const express = require('express')
const Router = require('./router')
const bodyParser = require('body-parser')
解析post所需字符串
// 解析 application/x-www-form-urlencoded (普通字符串)
server.use(bodyParser.urlencoded({ extended: false }))
// 解析 application/json (json字符串)
server.use(bodyParser.json())
  1. 全局中间件:
    • 直接在 index.js 中书写的中间件
    • 使用方式: server.use(以什么开头, 函数)
      • 以什么开头: 可以不写
      • 函数: 你这个中间件要做的事情
  2. 路由级中间件
    • 在路由中书写
    • 使用方式: Router.use(以什么开头, 函数)
      • 以什么开头: 可以不写
      • 函数: 你这个中间件要做的事情
  3. 请求级中间件
    • 在请求的处理中书写, 需要在路由处理函数之前书写
  4. 错误处理中间件(本质上就是全局中间件)
    • 必须放在监听端口号前一位,中间不能有其他代码

1.全局中间件

在开启服务和开启静态资源中间书写全局中间件
//1.1.1配置全局中间件
server.use((req,res,next) => {
  console.log('全局中间件触发了')

  /***
   * 中间件会有第三个参数next,他是一个函数,如果不调用,那么所有请求,都会卡在这个函数中
   */
  next()
})
需求:在每一次请求服务器时,记录一下

建立Index.txt文件

服务器页面导入第三方模块

const fs = require('fs')//node提供的内置模块

服务器页面引入文件记录

//1.1.1配置全局中间件,
server.use((req,res,next) => {
  /**
   * 需求:在每一次请求服务器时,记录一下
   * 
   * 解决:利用Node.js给我们提供的内置模块fs操作
  */
  
  fs.appendFile('./index.txt',`${new Date()}---${req.url}\n`,() => {})


  console.log('全局中间件触发了')

  /***
   * 中间件会有第三个参数next,他是一个函数,如果不调用,那么所有请求,都会卡在这个函数中
   */
  next()
})

2.路由级中间件:

 * 需求:在当前服务器中,只要是users开头的接口,全都需要登陆过
 * 换句话说,就是请求/users不管后续接口是什么,全都需要携带token
 * 所以我们为了方便减少代码量,好维护代码,我们就需要使用到路由级别的中间件

分表挂载路由级别中间件

//挂载路由级别的中间件
UsersRouter.use((req,res,next) => {
  // console.log('当前服务器接收到一条请求需要验证token')
  //1.验证token,如果token存在,那么继续向下进行,如果不存在,直接拦截,并且反馈给前端一个信息
  console.log(req.headers.authorization) //假设我们的token就是123455
  if(!req.headers.authorization) {
    res.send({
      code:0,
      msg:'当前接口需要传递token'
    })
    return
  }
  if(req.headers.authorization !== '123456') {
    res.send({
      code:0,
      msg:'当前token过期或者伪造'
    })
    return

  }
  next()
})
给ajax设置token

xhr.setRequestHeader('authorization','123456')

function myAjax2() {
    const xhr = new XMLHttpRequest()
    xhr.open('POST', '/api/users/info')
    xhr.onload = function () {
        console.log(JSON.parse(xhr.responseText))
    }
    xhr.setRequestHeader('authorization','123456')
    xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
    xhr.send('id=20040216')
}
myAjax2()

3.请求级中间件

请求中间件,一般用来验证参数

建立middleware文件夹内建立goods.js存放中间件函数

//该文件专门储存中间件函数
exports._getGoodList = (req,res,next) => {
  /**
   * 验证参数是否符合要求,如果符合继续向下,不符合直接拦截
  */
  const {current,pageSize} = req.query

  console.log(current,pageSize)

  //1.非空校验
  if(!current || !pageSize){
    res.send({
      code:0,
      msg:'参数数量不对,请检查'
    })
    return
  }
  /**
   * 2.格式校验
   * isNaN:会将传递进去的参数,转换为数字类型
   *        并且会验证是否为一个NaN
   *       '123' ->  123
   *        'abc'->  NaN
  */
  if(isNaN(current) || isNaN(pageSize)) {
    res.send({
      code:0,
      msg:'格式不对'
    })

    return
  }

  next()
}

路由分表挂载请求中添加中间件函数_getGoodList

//挂载请求
GoodsRouter.get('/list',_getGoodList,getGoodsList)

4.全局错误处理中间件

server.use((error,req,res,next) => {
  // console.log('全局处理开启成功')
  console.log(error)
  /**
   * 约定
   *    error === 2
   *        参数数量不够
   *    error === 3
   *        参数格式不对
   *    error === 4
   *        token没有传递
   *    error === 5
   *        token伪造过期
  */
  if(error === 2) {
    res.send({
      code:0,
      msg:'参数数量不够'
    })

  }else if(error === 3){
    res.send({
      code:0,
      msg:'参数格式不对'
    })
  }
  else if(error === 4){
    res.send({
      code:0,
      msg:'token没有传递'
    })
  }
  else if(error ===5){
    res.send({
      code:0,
      msg:' token伪造过期'
    })
  }
})
 * next如果直接调用,是进入到下一个中间件
 * 但是在调用的时候,还可以传递一个参数
 * 如果这个参数传递了值,会跳转到全局错误处理中间件
 * 然后全局错误处理中间件的第一个形参的值就是我们调用的时候传的参数

路由分表users.js在路由级别中间件中调用next


UsersRouter.use((req,res,next) => {
  console.log(req.headers.authorization) //假设我们的token就是123455
  if(!req.headers.authorization) {
    next(4)
    return
  }
  if(req.headers.authorization !== '123456') {
    next(5)
    return
  }
  next()
})

goods.js请求中间件函数中调用next

exports._getGoodList = (req,res,next) => {

  const {current,pageSize} = req.query

  console.log(current,pageSize)


  if(!current || !pageSize){
    next(2)
    return
  }

  if(isNaN(current) || isNaN(pageSize )) {
    next(3)
    return
  }
  

  next()
}
exports._getGoodInfo = (req,res,next) => {

  const {goodId} = req.query
  if(!goodId){
    next(2)
    return
  }

  next()
}