Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nodejs(二) 中间件 #7

Open
Alexandermclean opened this issue Mar 16, 2019 · 0 comments
Open

nodejs(二) 中间件 #7

Alexandermclean opened this issue Mar 16, 2019 · 0 comments
Labels
Node.js Node.js

Comments

@Alexandermclean
Copy link
Owner

3.中间件

中间件(Middleware)是一个函数,它可以访问请求对象(request object (req)),响应对象(response object (res)),和 web 应用中处于请求-响应循环流程中的中间件,一般被命名为 next 的变量。

关于next()函数的解释,我找了一篇比较好的文章

中间件的功能包括:

  • 执行任何代码;
  • 修改请求和响应对象;
  • 终结请求-响应循环;
  • 调用堆栈中的下一个中间件。
    如果当前中间件没有终结请求-响应循环,则必须调用 next()方法将控制权交给下一个中间件,否则请求就会挂起。

Express 应用可使用如下几种中间件:

  • 应用级中间件
  • 路由级中间件
  • 错误处理中间件
  • 内置中间件
  • 第三方中间件

1.应用级中间件

应用级中间件绑定到app对象使用app.use()和app.METHOD(),其中METHOD是需要处理的HTTP请求的方法,例如GET, PUT, POST 等等,全部小写。例如:

var app = express();

// 没有挂载路径的中间件,应用的每个请求都会执行该中间件
app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// 挂载至 /user/:id 的中间件,任何指向 /user/:id 的请求都会执行它
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// 路由和句柄函数(中间件系统),处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

下面这个例子展示了在一个挂载点装载一组中间件。

// 一个中间件栈,对任何指向 /user/:id 的 HTTP 请求打印出相关信息
app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

作为中间件系统的路由句柄,使得为路径定义多个路由成为可能。在下面的例子中,为指向 /user/:id 的 GET 请求定义了两个路由。第二个路由虽然不会带来任何问题,但却永远不会被调用,因为第一个路由已经终止了请求-响应循环。

// 一个中间件栈,处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
  console.log('ID:', req.params.id);
  next();
}, function (req, res, next) {
  res.send('User Info');
});

// 处理 /user/:id, 打印出用户 id
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id);
});

如果需要在中间件栈中跳过剩余中间件,调用 next('route') 方法将控制权交给下一个路由。 注意: next('route') 只对使用 app.VERB() 或 router.VERB() 加载的中间件有效。

// 一个中间件栈,处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
  // 如果 user id 为 0, 跳到下一个路由
  if (req.params.id == 0) next('route');
  // 否则将控制权交给栈中下一个中间件
  else next(); //
}, function (req, res, next) {
  // 渲染常规页面
  res.render('regular');
});

// 处理 /user/:id, 渲染一个特殊页面
app.get('/user/:id', function (req, res, next) {
  res.render('special');
});

2.路由级中间件

路由级中间件和应用级中间件一样,只是它绑定的对象为 express.Router()。

var router = express.Router();

路由级使用 router.use() 或 router.VERB() 加载。
上述在应用级创建的中间件系统,可通过如下代码改写为路由级:

var app = express();
var router = express.Router();

// 没有挂载路径的中间件,通过该路由的每个请求都会执行该中间件
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// 一个中间件栈,显示任何指向 /user/:id 的 HTTP 请求的信息
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// 一个中间件栈,处理指向 /user/:id 的 GET 请求
router.get('/user/:id', function (req, res, next) {
  // 如果 user id 为 0, 跳到下一个路由
  if (req.params.id == 0) next('route');
  // 负责将控制权交给栈中下一个中间件
  else next(); //
}, function (req, res, next) {
  // 渲染常规页面
  res.render('regular');
});

// 处理 /user/:id, 渲染一个特殊页面
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});

// 将路由挂载至应用
app.use('/', router);

路由级中间件和非路由级中间件的第三个参数next不是同一个next,功能上基本相同。

3.错误处理中间件

错误处理中间件有 4 个参数,定义错误处理中间件时必须使用这4个参数(4个参数是next(err)执行判断的标识)。即使不需要next对象,也必须在签名中声明它,否则中间件会被识别为一个常规中间件,不能处理错误。

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

具体关于错误处理中间件的介绍可以参考官方文档

4.内置中间件

express.static是Express唯一的内置中间件。它基于serve-static,负责在Express应用中托管静态资源。
最常用的用法在上面已经介绍过了,关于更细节的参数可参考官方文档

@Alexandermclean Alexandermclean changed the title nodejs-中间件 nodejs(二) 中间件 Mar 16, 2019
@Alexandermclean Alexandermclean added this to nodejs in nodejs Mar 16, 2019
@Alexandermclean Alexandermclean added this to nodejs in nodejs Mar 16, 2019
@Alexandermclean Alexandermclean added the Node.js Node.js label Mar 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Node.js Node.js
Projects
nodejs
  
nodejs
nodejs
nodejs
Development

No branches or pull requests

1 participant