express基础--中间件

116 阅读3分钟

以.use的都是中间件,顾名思义中间执行的比如

const express = require('express');

const app = express();

app.use((req, res, next) => {
  console.log(`请求日志:${req.method} ${req.url} ${new Date()}`);
  next(); // 放行
})

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

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

app.delete('/', (req, res) => {
  res.send('delete /')
})

const port = 3000;

app.listen(port, () => {
  console.log(`http://localhost:${port}/`);
})


可以发现无论任何请求都要先打印app.use里面的'请求日志'

2.怎么组成中间件

app.use('/', (req, res, next) => {  // 其中use可以是get、post等,用于限定请求路径
    next();		// 这个例子就是所有请求路径为根路径的请求都会通过这个中间件
    			// 如果当前中间件没有结束请求相应周期,则需要通过next()调用下一个中间件,否则,该请求将会被挂起
})

3.中间件能做什么

  • 执行任何代码
  • 获取req和res,并修改它们
  • 结束请求,或者调用下一个中间件

4.不同的中间件示例

4.1 没有任何修改,限制的中间件

所有请求都会通过它

app.use(function (req, res, next) {
  res.send('不做任何限定的中间件');
})

4.2 有请求路径

只有请求路径匹配才会通过它

app.use('/user/:id', function (req, res, next) {
  res.send('限定请求路径的中间件');
})

4.3 有请求方法+请求路径

当然这也是一个中间件

app.get('/', (req, res) => {
  res.send('限定请求方法 + 请求路径的中间件');
})

4.4 多次处理

app.use(function (req, res, next) {
  console.log('第一次处理');
  next();    // 这个next()之后就是第二个处理函数
}, function (req, res, next) {
  console.log('第二次处理');
  next();    // 这个next()之后则是脱离当前处理栈,往后寻找匹配调用
})

或者调用回调函数数组

const first = (req, res, next) => {
  console.log('第一次处理');
  next();
};

const second = (req, res, next) => {
  console.log('第二次处理');
  next();
};

app.use([first, second]);

4.5 多个路由处理函数

app.use('/', (req, res, next) => {
  console.log('第一个路由处理函数');
  next();   // 如果这里是res.end(),那么就会结束响应。第二个路由处理函数就没有机会执行
})
app.use('/', (req, res, next) => {
  console.log('第二个路由处理函数');
  res.end();
})

4.6中间件子堆栈

app.get('/:id', function (req, res, next) {
  if (req.params.id === '0') {
    next('route');  // 跳过当前堆栈之后的所有中间件。即不执行后面的处理函数,而是直接去执行后面的路由处理函数
      			   // (处理函数和路由处理函数看上面的例子)
  } else {
    next();
  }
}, function (req, res, next) {
  res.send('regular');
})

app.get('/:id', function (req, res, next) {
  res.send('special');
})

上面例子中,动态参数id不为0时,第一个处理函数会调用next(),然后会执行第二个处理函数,然后会收到regular的响应。而当id为0时,会调用next(‘route’),会跳过当前堆栈之后的所有中间件。即不执行后面的处理函数,而是直接去执行后面的路由处理函数。所以不会打印regular,而是打印special。

5.路由中间件

单独封装出router.js

const express = require('express');

// 1.创建路由实例
const router = express.Router();

// 2. 配置路由
router.get('/aaa', (req, res) => {
  res.send('get /aaa');
})

router.post('/bbb', (req, res) => {
  res.send('post /bbb');
})

// 3. 导出路由实例
module.exports = router

// 4. 将路由挂载(集成)到Express实例应用中(见app.js)

然后在app.js去导入

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

const router = require('./router.js');

app.get('/', (req, res) => {
  res.send('Hello World!');
})

// 4. 将路由挂载(集成)到Express实例应用中
app.use('/abc', router);		// 给路由限定访问前缀/abc

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

abc是这个路由的限制前缀,router.js里面定义的路由需要加上这个前缀,不然404

6.错误处理中间件

app.use((err, req, res, next) => {   // 四个参数都要有才是错误处理中间件。如果只有err、req、res,则err实际上是req对象
  console.log('错误: ', err);
  res.status(500).json({
    error: err.message
  })
})

四个参数都要有才是错误处理中间件。如果只有err、req、res,则err实际上是req对象

7 内置中间件

express.json():解析Content-Type为application/json格式的请求体 express.urlencoded():解析Content-Type为application/x-www-form-urlencoded格式的请求体 express.raw():解析Content-Type为application/octet-stream格式的请求体 express.text():解析Content-Type为text/plain格式的请求体 express.static():托管静态资源文件

8第三方中间件

Express middleware