中间件和app.use在Expressjs中是什么意思?

我看到的几乎每个Express应用程序都有一个用于中间件的app.use语句,但我还没有找到一个清晰、简洁的解释,说明中间件实际上是什么以及app.use语句的作用。甚至express文档本身在这一点上也有点模糊。你能给我解释一下这些概念吗?

98274 次浏览

中间件

在一个新项目中,我已经把中间件的概念分离了一半。

中间件允许您定义应该流经的操作堆栈。Express服务器本身就是一堆中间件。

// express
var app = express();
// middleware
var stack = middleware();

然后你可以通过调用.use向中间件堆栈中添加层

// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
next();
});

中间件堆栈中的一层是一个函数,它接受n个参数(2表示express, req &res)和next函数。

中间件期望该层做一些计算,增加参数,然后调用next

除非你处理它,否则堆栈不会做任何事情。每当在服务器上捕获到传入的HTTP请求时,Express将处理堆栈。对于中间件,您可以手动处理堆栈。

// express, you need to do nothing
// middleware
stack.handle(someData);

一个更完整的例子:

var middleware = require("../src/middleware.js");


var stack = middleware(function(data, next) {
data.foo = data.data*2;
next();
}, function(data, next) {
setTimeout(function() {
data.async = true;
next();
}, 100)
}, function(data) {
console.log(data);
});


stack.handle({
"data": 42
})

用简单的术语来说,您只需定义一个操作堆栈,以便为每个传入的HTTP请求表示处理。

在express(而不是connect)方面,有全局中间件和特定于路由的中间件。这意味着您可以将中间件堆栈附加到每个传入的HTTP请求上,或者仅将其附加到与特定路由交互的HTTP请求上。

express &中间件:

// middleware


var stack = middleware(function(req, res, next) {
users.getAll(function(err, users) {
if (err) next(err);
req.users = users;
next();
});
}, function(req, res, next) {
posts.getAll(function(err, posts) {
if (err) next(err);
req.posts = posts;
next();
})
}, function(req, res, next) {
req.posts.forEach(function(post) {
post.user = req.users[post.userId];
});


res.render("blog/posts", {
"posts": req.posts
});
});


var app = express.createServer();


app.get("/posts", function(req, res) {
stack.handle(req, res);
});


// express


var app = express.createServer();


app.get("/posts", [
function(req, res, next) {
users.getAll(function(err, users) {
if (err) next(err);
req.users = users;
next();
});
}, function(req, res, next) {
posts.getAll(function(err, posts) {
if (err) next(err);
req.posts = posts;
next();
})
}, function(req, res, next) {
req.posts.forEach(function(post) {
post.user = req.users[post.userId];
});


res.render("blog/posts", {
"posts": req.posts
});
}
], function(req, res) {
stack.handle(req, res);
});

经过简化之后,web服务器可以被看作是一个接收请求并输出响应的函数。因此,如果您将web服务器视为一个功能,您可以将其组织成几个部分,并将它们分离为更小的功能,以便它们的组合将是原始功能。

中间件是可以与其他函数组合的较小函数,其明显的好处是可以重用它们。

我添加了一个后期的答案,添加一些在之前的答案中没有提到的东西。

到目前为止,应该已经清楚中间件是在客户端请求服务器的答案之间运行的函数。最常见的中间件功能是错误管理、数据库交互、从静态文件或其他资源获取信息。要在中间件堆栈上移动,必须调用下一个回调,您可以在中间件函数的末尾看到它移动到流程中的下一个步骤。

你可以使用app.use方法,并有一个流像这样:

var express = require('express'),
app = express.createServer(),
port = 1337;


function middleHandler(req, res, next) {
console.log("execute middle ware");
next();
}


app.use(function (req, res, next) {
console.log("first middle ware");
next();
});


app.use(function (req, res, next) {
console.log("second middle ware");
next();
});


app.get('/', middleHandler, function (req, res) {
console.log("end middleware function");
res.send("page render finished");
});


app.listen(port);
console.log('start server');

但是您也可以使用另一种方法,将每个中间件作为函数参数传递。这里是一个MooTools Nodejs网站的例子,中间件在response被发送回客户端之前获得Twitter, Github和Blog流。注意函数是如何作为参数在app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){中传递的。使用app.get只会对GET请求调用,app.use将对所有请求调用。

// github, twitter & blog feeds
var githubEvents = require('./middleware/githubEvents')({
org: 'mootools'
});
var twitter = require('./middleware/twitter')();
var blogData = require('./blog/data');
function getLatestBlog(req, res, next){
blogData.get(function(err, blog) {
if (err) next(err);
res.locals.lastBlogPost = blog.posts[0];
next();
});
}


// home
app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){
res.render('index', {
title: 'MooTools',
site: 'mootools',
lastBlogPost: res.locals.lastBlogPost,
tweetFeed: res.locals.twitter
});
});

中间件是在输入/源产生输出后在中间执行的函数,该输出可以是最终输出,也可以被下一个中间件使用,直到循环完成。

它就像一个经过流水线的产品,在移动过程中不断修改,直到完成、评估或被拒绝。

中间件期望处理某些值(即参数值),并且基于某些逻辑,中间件将调用或不调用下一个中间件,或将响应发送回客户端。

如果您仍然不能理解中间件的概念,那么它在某种程度上类似于Decorator或命令链模式。

简单点,伙计!

注意:答案与ExpressJS内置中间件用例有关,但是中间件有不同的定义和用例。

从我的角度来看,中间件作为实用程序或辅助函数,但它的激活和使用是完全可选的通过使用app.use('path', /* define or use builtin middleware */),它不希望我们写一些代码来完成非常常见的任务,这些任务是我们客户端每个HTTP请求所需要的,比如处理cookie, CSRF令牌和……,在大多数应用程序所以中间件可以帮助我们对客户端的每个HTTP请求进行堆栈、序列或操作顺序,然后将处理结果作为客户端请求的单个单元提供中非常常见。

例子:

接受客户端请求并根据他们的请求提供响应是web服务器技术的本质。

想象一下,如果我们向我们的web服务器的根URI的GET HTTP请求提供一个只有“Hello, world!”文本的响应,这是非常简单的场景,不需要任何其他东西,但是如果我们检查当前登录的用户,然后响应“Hello,“Username!”需要比平时更多的东西,在这种情况下,我们需要一个中间件来处理所有客户端请求元数据,并向我们提供从客户端请求中抓取的身份信息,然后根据这些信息,我们可以唯一地识别当前用户,并有可能用一些相关数据响应他/她。

希望它能帮助到别人!

中间件是在调用用户定义的处理程序之前由Express js路由层调用的链式函数的子集。中间件函数可以完全访问请求和响应对象,并且可以修改它们中的任何一个 中间件链总是按照定义它的顺序被调用,所以对您来说,确切地知道某个特定的中间件在做什么是至关重要的。一旦一个中间件函数完成,它将调用链中的下一个函数,通过调用它的下一个参数作为函数。
在整个链被执行之后,调用用户请求处理程序

expressjs 指南对你的问题有一个非常简洁的回答,我强烈建议你去读,我发布了一个简短的指南片段,指南是相当好的。

编写用于Express应用程序的中间件

概述

中间件< em > < / em >函数是可以访问应用程序请求-响应循环中的请求对象 (要求的事情)、响应对象 (res)和下一个函数的函数。下一个函数是Express路由器中的一个函数,当它被调用时,执行当前中间件之后的中间件。

中间件函数可以执行以下任务:

  • 执行任何代码。
  • 对请求和响应对象进行更改。
  • 结束请求-响应循环。
  • 调用堆栈中的下一个中间件。

如果当前中间件函数没有结束请求-响应循环,它必须调用next ()来将控制权传递给下一个中间件函数。否则,请求将被挂起。

enter image description here

例子

下面是一个简单的“Hello World”Express应用程序示例。本文的其余部分将定义并向应用程序添加两个中间件函数:一个名为myLogger,用于打印简单的日志消息,另一个名为requestTime1,用于显示HTTP请求的时间戳。

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


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


app.listen(3000)

中间件功能myLogger

下面是一个名为“myLogger”的中间件函数的简单示例。当应用程序的请求通过该函数时,该函数只打印“LOGGED”。中间件函数被分配给一个名为myLogger的变量。

var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}

注意上面对next ()的调用。调用此函数将调用应用程序中的下一个中间件函数。next ()函数不是Node.js或Express API的一部分,而是传递给中间件函数的第三个参数。next ()函数可以被命名为任何东西,但按照惯例,它总是被命名为" next "。为了避免混淆,请始终使用此约定。

要加载中间件函数,调用app.use (),指定中间件函数。例如,下面的代码在路由到根路径(/)之前加载myLogger中间件函数。

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


var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}


app.use(myLogger)


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


app.listen(3000)

每次应用程序接收到请求时,它都会将消息“LOGGED”打印到终端。

中间件加载的顺序很重要:首先加载的中间件函数也会首先执行。

如果myLogger是在到根路径的路由之后加载的,请求永远不会到达它,应用程序也不会打印“LOGGED”,因为根路径的路由处理程序终止了请求-响应周期。

中间件函数myLogger只是打印一条消息,然后通过调用next ()函数将请求传递给堆栈中的下一个中间件函数。

人力资源> < p > <

  1. 这篇文章将只包含myLogger中间件,对于进一步的文章,你可以去最初的expressjs指南在这里

< / >共舞,

=====非常非常简单的解释=====

中间件通常用于Express.js框架的上下文中,是node.js的基本概念。简而言之,它基本上是一个可以访问应用程序的请求和响应对象的函数。我想要思考的方式是,在请求被应用程序处理之前,它要经过一系列的“检查/预筛选”。例如,中间件可以在请求进入应用程序之前确定请求是否经过身份验证,如果请求未经过身份验证则返回登录页面,或者用于记录每个请求。有很多第三方中间件可以支持各种功能。

简单的中间件示例:

var app = express();
app.use(function(req,res,next)){
console.log("Request URL - "req.url);
next();
}

上面的代码将对每个进入的请求执行,并记录请求url, next()方法本质上允许程序继续。如果没有调用next()函数,则程序将不会继续,并将在中间件执行时停止。

中间件的几个陷阱:

  1. 应用程序中中间件的顺序很重要,因为请求将按顺序通过每个中间件。
  2. 忘记调用中间件函数中的next()方法可能会中断请求的处理。
  3. 中间件函数中req和res对象的任何更改,都将使应用程序中使用req和res的其他部分可用
在非常基本的术语中,如果我想这样解释它,我是从traversymedia youtube频道express速成课程中学到的。
中间件是一个函数,它在你调用你的路由后执行,像这样
var logger = function(req, res, next){
console.log('logging...');
next();
}


app.use(logger);

这个记录器函数在你每次刷新页面时执行这意味着你可以在页面呈现后写任何你需要做的事情任何api调用,重置基本上任何事情。把这个中间件放在你的路由功能之前,中间件的顺序非常重要,否则它就无法工作