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 相关文章推荐
javascript中万恶的function实例分析
May 25 Javascript
JavaScript语言核心数据类型和变量使用介绍
Aug 23 Javascript
js实现精美的图片跟随鼠标效果实例
May 16 Javascript
浅谈JavaScript中的字符编码转换问题
Jul 07 Javascript
AngularJS模板加载用法详解
Nov 04 Javascript
Bootstrap CSS布局之表单
Dec 17 Javascript
JavaScript函数绑定用法实例分析
Nov 14 Javascript
浅谈React高阶组件
Mar 28 Javascript
操作按钮悬浮固定在微信小程序底部的实现代码
Aug 02 Javascript
Vue数据绑定实例写法
Aug 06 Javascript
JavaScript监听键盘事件代码实现
Jun 03 Javascript
小程序实现多个选项卡切换
Jun 19 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
mysql_fetch_row,mysql_fetch_array,mysql_fetch_assoc的区别
2009/04/24 PHP
php 智能404跳转代码,适合换域名没改变目录的网站
2010/06/04 PHP
php tp验证表单与自动填充函数代码
2012/02/22 PHP
浅谈thinkphp的实例化模型
2015/01/04 PHP
php多线程实现方法及用法实例详解
2015/10/26 PHP
javascript 原型继承介绍
2011/08/30 Javascript
js定时器(执行一次、重复执行)
2014/03/07 Javascript
jQuery图片切换插件jquery.cycle.js使用示例
2014/06/16 Javascript
jQuery对象初始化的传参方式
2015/02/26 Javascript
AngularJS的表单使用详解
2015/06/17 Javascript
JavaScript控制浏览器全屏及各种浏览器全屏模式的方法、属性和事件
2015/12/20 Javascript
JavaScript位置与大小(1)之正确理解和运用与尺寸大小相关的DOM属性
2015/12/26 Javascript
JavaScript学习小结之被嫌弃的eval函数和with语句实例详解
2016/08/01 Javascript
Vue路由跳转问题记录详解
2017/06/15 Javascript
angularjs实现柱状图动态加载的示例
2017/12/11 Javascript
Nuxt.js踩坑总结分享
2018/01/18 Javascript
如何编写一个d.ts文件的步骤详解
2018/04/13 Javascript
Vue实现PopupWindow组件详解
2018/04/28 Javascript
垃圾回收器的相关知识点总结
2018/05/13 Javascript
Vue源码解析之Template转化为AST的实现方法
2018/12/14 Javascript
vue2.0项目集成Cesium的实现方法
2019/07/30 Javascript
[02:15]2015国际邀请赛选手档案IG.Ferrari 430
2015/07/30 DOTA
python 生成器生成杨辉三角的方法(必看)
2017/04/10 Python
Python调用微信公众平台接口操作示例
2017/07/08 Python
Python随机生成身份证号码及校验功能
2018/12/04 Python
Python3 实现串口两进程同时读写
2019/06/12 Python
pytorch 输出中间层特征的实例
2019/08/17 Python
解决python明明pip安装成功却找不到包的问题
2019/08/28 Python
基于Keras 循环训练模型跑数据时内存泄漏的解决方式
2020/06/11 Python
Python自动化测试中yaml文件读取操作
2020/08/20 Python
纽约家具、家居装饰和地毯店:ABC Carpet & Home
2017/06/21 全球购物
班主任经验交流材料
2014/12/16 职场文书
房地产销售助理岗位职责
2015/04/14 职场文书
《成长的天空》读后感3篇
2019/12/06 职场文书
Python中tkinter的用户登录管理的实现
2021/04/22 Python
Spring mvc是如何实现与数据库的前后端的连接操作的?
2021/06/30 Java/Android