express.js中间件说明详解


Posted in Javascript onMarch 19, 2019

express的新开发人员往往对路由处理程序和中间件之间的区别感到困惑。因此他们也对app.use(),app.all(),app.get(),app.post(),app.delete()和app.put()方法的区别感到困惑。

在本文中,我将解释中间件和路由处理程序之间的区别。以及如何正确使用app.use(),app.all(),app.get(),app.post(),app.delete()和app.put()方法。

路由处理

app.use(),app.all(),app.get(),app.post(),app.delete()和app.put()全部是用来定义路由的。这些方法都用于定义路由。路由用于处理HTTP请求。路由是路径和回调的组合,在请求的路径匹配时执行。回调被称为路由处理程序。

它们之间的区别是处理不同类型的HTTP请求。例如: app.get()方法仅仅处理get请求,而app.all()处理GET、POST等请求。

下面是一个例子,如何定义一个路由:

var app = require("express")();

app.get("/", function(req, res, next){
  res.send("Hello World!!!!");
});

app.listen(8080);

每个路由处理程序都获得对当前正在提供的HTTP请求的请求和响应对象的引用。

可以为单个HTTP请求执行多个路由处理程序。这是一个例子:

var app = require("express")();

app.get("/", function(req, res, next){
  res.write("Hello");
  next();
});

app.get("/", function(req, res, next){
  res.write(" World !!!");
  res.end();
});

app.listen(8080);

这里第一个句柄写入一些响应,然后调用next()。 next()方法用于调用与路径路径匹配的下一个路由处理程序。

路由处理程序必须结束请求或调用下一个路由处理程序。

我们还可以将多个路由处理程序传递给app.all(),app.get(),app.post(),app.delete()和app.put()方法。

这是一个证明这一点的例子:

var app = require("express")();

app.get("/", function(req, res, next){
  res.write("Hello");
  next();
}, function(req, res, next){
  res.write(" World !!!");
  res.end();
});

app.listen(8080);

中间件

中间件是一个位于实际请求处理程序之上的回调。它采用与路由处理程序相同的参数。

要了解中间件,我们来看一个带有dashboard和profile页面的示例站点。要访问这些页面,用户必须登录。还会记录对这些页面的请求。

以下是这些页面的路由处理程序的代码:

var app = require("express")();

function checkLogin(){
  return false;
}

function logRequest(){
  console.log("New request");
}

app.get("/dashboard", function(req, res, next){

  logRequest();

  if(checkLogin()){
    res.send("This is the dashboard page");
  }
  else{
    res.send("You are not logged in!!!");
  }
});

app.get("/profile", function(req, res, next){

  logRequest();

  if(checkLogin()){
    res.send("This is the dashboard page");
  }
  else{
    res.send("You are not logged in!!!");
  }
});

app.listen(8080);

这里的问题是有很多重复的代码,即我们不得不多次使用logRequest()和checkLogin()函数。这也使得更新代码变得困难。因此,为了解决这个问题,我们可以为这两条路径编写一条通用路径。

这是重写的代码:

var app = require("express")();

function checkLogin(){
  return false;
}

function logRequest(){
  console.log("New request");
}

app.get("/*", function(req, res, next){
  logRequest();
  next();
})

app.get("/*", function(req, res, next){
  if(checkLogin()){
    next();
  }
  else{
    res("You are not logged in!!!");
  }
})

app.get("/dashboard", function(req, res, next){
  res.send("This is the dashboard page");
});

app.get("/profile", function(req, res, next){
  res.send("This is the dashboard page");
});

app.listen(8080);

这里的代码看起来更清晰,更易于维护和更新。这里将前两个定义的路由处理程序称为中间件,因为它们不处理请求,而是负责预处理请求。

Express为我们提供了app.use()方法,该方法专门用于定义中间件。 app.use()方法可能看起来与app.all()类似,但它们之间存在很多差异,这使得app.use()非常适合于声明中间件。让我们看看app.use()方法是如何工作的:

app.use() 和 app.all() 的不同:

CALLBACK

app.use()只需要一个回调,而app.all()可以进行多次回调。

PATH

app.use()只查看url是否以指定路径开头,app.all()匹配完整路径。

这里有一个例子来说明:

app.use( "/product" , mymiddleware);
// will match /product
// will match /product/cool
// will match /product/foo

app.all( "/product" , handler);
// will match /product
// won't match /product/cool  <-- important
// won't match /product/foo  <-- important

app.all( "/product/*" , handler);
// won't match /product    <-- Important
// will match /product/cool
// will match /product/foo

NEXT()

中间件内的next()调用下一个中间件或路由处理程序,具体取决于接下来声明的那个。但是路由处理程序中的next()仅调用下一个路由处理程序。如果接下来有中间件,则跳过它。因此,必须在所有路由处理程序之前声明中间件。

这里有一个例子来说明:

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

app.use(function frontControllerMiddlewareExecuted(req, res, next){
 console.log('(1) this frontControllerMiddlewareExecuted is executed');
 next();
});

app.all('*', function(req, res, next){
 console.log('(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next');
 next();
});

app.all('/hello', function(req, res, next){
 console.log('(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next');
 next();
});

app.use(function frontControllerMiddlewareNotExecuted(req, res, next){
 console.log('(4) this frontControllerMiddlewareNotExecuted is not executed');
 next();
});

app.get('/hello', function(req, res){
 console.log('(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response');
 res.send('Hello World');
});

app.listen(80);

现在我们看到了app.use()方法的唯一性以及它用于声明中间件的原因。

让我们重写我们的示例站点代码:

var app = require("express")();

function checkLogin(){
  return false;
}

function logRequest(){
  console.log("New request");
}

app.use(function(req, res, next){
  logRequest();
  next();
})

app.use(function(req, res, next){

  if(checkLogin()){
    next();
  }
  else{
    res.send("You are not logged in!!!");
  }
})

app.get("/dashboard", function(req, res, next){
  res.send("This is the dashboard page");
});

app.get("/profile", function(req, res, next){
  res.send("This is the dashboard page");
});

app.listen(8080);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery命名冲突解决的五种方案分享
Mar 16 Javascript
jquery 根据name名获取元素的value值
Feb 27 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
May 12 Javascript
深入理解vue.js双向绑定的实现原理
Dec 05 Javascript
Iphone手机、安卓手机浏览器控制默认缩放大小的方法总结(附代码)
Aug 18 Javascript
使用vue官方提供的模板vue-cli搭建一个helloWorld案例分析
Jan 16 Javascript
Vue的轮播图组件实现方法
Mar 03 Javascript
vue项目部署到Apache服务器中遇到的问题解决
Aug 24 Javascript
Node.js EventEmmitter事件监听器用法实例分析
Jan 07 Javascript
解决element ui select下拉框不回显数据问题的解决
Feb 20 Javascript
js针对图片加载失败的处理方法分析
Aug 24 Javascript
微信小程序静默登录的实现代码
Jan 08 Javascript
js array数组对象操作方法汇总
Mar 18 #Javascript
浅析JavaScript异步代码优化
Mar 18 #Javascript
js实现图片局部放大效果详解
Mar 18 #Javascript
详解在React项目中安装并使用Less(用法总结)
Mar 18 #Javascript
vue动画效果实现方法示例
Mar 18 #Javascript
node.js实现微信开发之获取用户授权
Mar 18 #Javascript
学习node.js 断言的使用详解
Mar 18 #Javascript
You might like
Php+SqlServer实现分页显示
2006/10/09 PHP
PHP实现采集程序原理和简单示例代码
2007/03/18 PHP
php判断变量类型常用方法
2012/04/24 PHP
destoon整合ucenter后注册页面不跳转的解决方法
2014/06/21 PHP
php使用cookie实现记住用户名和密码实现代码
2015/04/27 PHP
php获取json数据所有的节点路径
2015/05/17 PHP
PHP自定义函数获取汉字首字母的方法
2016/12/01 PHP
PHP中md5()函数的用法讲解
2019/03/30 PHP
BOOM vs RR BO3 第二场2.13
2021/03/10 DOTA
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
jQuery通过控制节点实现仅在前台通过get方法完成参数传递
2015/02/02 Javascript
JQuery插件Marquee.js实现无缝滚动效果
2016/04/26 Javascript
JavaScript通过HTML的class来获取HTML元素的方法总结
2016/05/24 Javascript
前端微信支付js代码
2016/07/25 Javascript
详解vuejs之v-for列表渲染
2017/06/22 Javascript
vue框架搭建之axios使用教程
2018/07/11 Javascript
Vue+abp微信扫码登录的实现代码示例
2020/01/06 Javascript
加速vue组件渲染之性能优化
2020/04/09 Javascript
Vue为什么要谨慎使用$attrs与$listeners
2020/08/27 Javascript
使用优化器来提升Python程序的执行效率的教程
2015/04/02 Python
Python selenium实现微博自动登录的示例代码
2018/05/16 Python
对python中词典的values值的修改或新增KEY详解
2019/01/20 Python
flask 实现token机制的示例代码
2019/11/07 Python
基于python爬取有道翻译过程图解
2020/03/31 Python
django model通过字典更新数据实例
2020/04/01 Python
Python数据模型与Python对象模型的相关总结
2021/01/26 Python
基于Modernizr 让网站进行优雅降级的分析
2013/04/21 HTML / CSS
美国智能家居专家:tink
2019/06/04 全球购物
青春飞扬演讲稿
2014/09/11 职场文书
科长个人四风问题整改措施思想汇报
2014/10/13 职场文书
企业投资意向书
2015/05/09 职场文书
庭外和解协议书
2016/03/23 职场文书
2016年教师党员承诺书范文
2016/03/24 职场文书
pandas中DataFrame检测重复值的实现
2021/05/26 Python
正则表达式拆分url实例代码
2022/02/24 Java/Android
python+pyhyper实现识别图片中的车牌号思路详解
2022/12/24 Python