Express快速上手

292 阅读1分钟

介绍

  Express以它的简单、易用,可以快速创建强大Api而闻名。本文章是我学习它所做的笔记,包括基础用法和技巧。Express官网文档

基础

const express = require('express')

const app = express()
const port = 8080

app.use('/',(req, res)=>{ // 当访问根目录 '/' 时会返回 'hello world'
  res.send('hello world')
})

/** 
* 访问 '/api' 时该回调不会执行
* 因为它前面的 '/api' 中的 '/' 被会上面匹配
*/  
app.use('/api',(req, res)=>{ 
  res.send('hello api')
})

app.listen(port, () => {
  console.log(`running on port ${port}`)
})

  app.use是使用中间件的方法,里面的回调函数被称为中间件。

中间件

基础

app.use('/api',(req, res, next) => {
    console.log(0)
    next()     // 前面的函数执行完以后,只有执行next,下一个中间件才能执行
  }, (req, res, next) => {
    console.log(1)
    next()
  }, (req, res) => {
    console.log(2)
  }
)

  下面是与上面等价的代码:

const middleware = [
  (req, res, next) => {
    console.log(0)
    next()
  },
  (req, res, next) => {
    console.log(1)
    next()
  },
  (req, res) => {
    console.log(2)
  },
]

app.use('/api',middleware)

  Express 根据访问的url匹配对应的函数。有多个函数的话就按照书写的顺序执行,就像将函数放入了队列中。

路由

基础用法

  路由也叫路由中间件。路由中间件写什么路径就匹配什么(可以是正则),和use不同。

router.get('/index',(req, res)=>{ // 'index' 可以是正则
  res.send('<h1>index page.</h1>')
})

  通过上面的方法可以猜测出来,除了get,应该还存在着postput之类的方法。通过跳转到定义,发现果然如此,下面是源码中的接口:

export interface IRouterMatcher<
    T,
    Method extends 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head' = any
>

  就算不会TypeScript也可以猜出来,有多个对应着请求方式的方法,除了那个all。这个all方法也可以望词生意,匹配所有HTTP请求的方式。通常使用来加中间件的,如下:

app.all('/auth', function (req, res, next) {
  // 对任何访问auth接口的请求进行权限校验
  next() // 继续执行下面的代码
})

拆分文件

  通常来说一个应用的接口是较多的,如果全写在一个文件,不方便维护。可以路由部分拆出来,方法如下,下面是主文件(/server.js):

const express = require('express')

const app = express()
const router = require('./router') // 路由文件在同级目录的router文件夹下 /router/index.js
const port = 8080

app.use(router) // 没写路径使用中间件会处理所有请求,但是不会影响其它的路由路径。

app.listen(port, () => {
  console.log(`running on port ${port}`)
})

  下面是路由文件(/router/index.js):

const express = require('express')

const router = express()

router.get('/index',(req,res)=>{
  res.send('<h1>index page.</h1>')
})

module.exports = router

获取前端传来的参数

  有两种方式:

  • 通过req.query
  • 通过req.params
router.get('/index/:id', (req, res) => {
  const query = req.query
  const params = req.params
  res.json({ ...query, ...params }) // 以json返回query与params中的所有属性
})

  下面是上面代码请求url后的效果: image.png

拆分出控制器

  当路由开始多起来后会发现代码看起来挺不方便的,可以拆分出controller(就是将路由对应的方法拆分出去),如下:

// 路由文件
const express = require('express')

const router = express()
const { list } = require('../controller')

router.get('/list',list) 

  controller如下:

const list = (req,res,next)=>{
  res.json([
    {name: 'bob',age: 18},
    {name: 'jerry',age: 19}
  ])
}

exports.list = list

  当前目录结构如下:

image.png