03-blog-route和中间件

160 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

路由模块

数据库与模块之间已经建立成功,现在开始做路由。

先在app.js中测试一下路由是否有效:

 app.get('/',(req,res)=>{
        res.json({status:"API is running"})
    })

输入localhost:3000可以访问到json字符串status:"API is running",说明路由成功;开始思考将路由抽离。

抽离路由模块

将initRoute函数初始化作为一切的路由入口,使用app.js中的express下的app,通过app来写get/post方法。

image.png

const initRoute = (app)=>{
    app.get('/',(req,res)=>{
        res.json({status:"API is running"})
    })
}
module.exports = initRoute;

在app.js中调用该方法,并同时把app传入该函数

app.js
const initRoute = require("./init/initRoute")
initRoute(app)

再次测试,还是可以在localhost:3000访问json数据。------转移成功。

创建user部分路由:/api/v1/users(接口/版本号/用户部分的路由)

image.png

在user.js下写接口,引入router()

const express = require("express")
const router = express.Router()

router.get("/api/v1/users",(req,res)=>{
    console.log("getdata");
    res.json({ //数据自定义,随便写格式
        status:200,
        message:"success",
        data:{
            code:1,
            data:{
                name:"hello"
            },
            message:"请求成功"
        }
    })
})

router.post('/api/v1/users',(req,res)=>{
    console.log("控制器处理逻辑");
})

module.exports=router

因为/api/v1/users中存在一个公共部分,比如说/api/v1/article,/api/v1/tags,这些。

所以考虑抽离出路由的公共部分。

在初始路由initRoute.js处引入该定义完成的user.js

const userRoute = require("../routes/user")

并使用app.use()方法来替代公共路由部分

app.use("/api/v1/users",userRoute)//第一个参数:公共部分,第二个参数路由:路由模块

这样,就做到了在use.js中的路由可以无需写公共部分。即,路由抽离。

这样user.js中的参数就可以为空了,因为已经被抽离啦。

user.js
router.get("",(req,res)=>{  //第一个参数可以为空了
    res.json({ //数据自定义,随便写格式
        status:200,
        message:"success",
        data:{
            code:1,
            data:{
                name:"hello"
            },
            message:"请求成功"
        }
    })
})

中间件

安装cors中间件

官方解释:

CORS是一个Node.js包,用于提供一个Connect/Express中间件,
该中间件可用于启用具有各种选项的CORS。

解析中间件

app.use(express,json()) //解析请求

express.json()是Express中的内置中间件函数

引入请求日志中间件

morgan:面向Node.js的HTTP请求记录器中间件

每次http请求,express都会输出日志,并使用一致的格式在终端输出。

image.png

定义404中间件

如果请求的结果不存在,则应该返回404错误处理,该中间件我们自己去定义。

noMatchMiddleware.js
const noMatchMiddleware =(req,res,next)=>{
    res
    .status(404)
    .json({
        code:0,
        message:"router url not found"
    })
}
module.exports = noMatchMiddleware

在app.js中使用404中间件

const noMatchMiddleware = require("./middleware/noMatchMiddleware")
app.use(noMatchMiddleware)

当访问不存在的随便页面时,出现如下:

image.png

进阶自定义捕捉错误中间件

  1. 定义类组件

因为是自定义打印错误的中间件,所以要先有一个类组件,上面挂载了status,message,error,每出现一次错误就会调用一次该函数组件并打印出来。

//自定义错误组件=>状态码,信息,错误点
class HttpException extends Error{
    constructor(status,message,errors){
        super()
        this.status=status
        this.message=message
        this.errors=errors
    }
}

module.exports = HttpException
  1. 捕捉错误中间件

好比捕捉404中间件一样,可以将信息挂载到实例上,成为对象然后打印出来每一个属性。

const HttpException = require("../exception/httpException")
//当404的时候,就去调用类组件,将404的信息new一个实例对象
const noMatchMiddleware =(req,res,next)=>{
   const noMatchError = new HttpException(404,"访问路径不匹配","router url not found")
   //调用next
   next(noMatchError)  //注意这里
}

module.exports = noMatchMiddleware

为什么会有一个next()呢,回看app.js。

捕捉到错误之后,传递给捕捉所有的错误的中间件(不止404),起名为errorMiddleware。

所以在app.js中先app.use noMatchMiddleware在use errorMiddleware。

使得捕捉错误之后next(),将error对象传递给打印所有错误的中间件。

//这里的error就会接到next()传递过来的错误对象数据了
const errorMiddleware = (error,req,res,next)=>{
    const status = error.status||500
    const message = error.message||"服务器端错误"
    const errors = error.errors||"服务器端错误"
    res.status(status)
       .json({
        code:0,
        message:message,
        errors:errors
       })
}
module.exports = errorMiddleware

image.png

最终成功获得到所有错误的打印信息。

今日进度:

image.png