node.js 在 Expressjs 中中间件和 app.use 实际上是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7337572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does middleware and app.use actually mean in Expressjs?
提问by iZ.
Almost every Express app I see has an app.usestatement for middleware but I haven't found a clear, concise explanation of what middleware actually is and what the app.usestatement is doing. Even the express docs themselves are a bit vague on this. Can you explain these concepts for me please?
我看到的几乎每个 Express 应用程序都有一个app.use关于中间件的声明,但我还没有找到关于中间件究竟是什么以及该app.use声明在做什么的清晰、简洁的解释。甚至快递文档本身对此也有点含糊。你能帮我解释一下这些概念吗?
采纳答案by Raynos
I'm halfway through separating the concept of middleware in a new project.
我正在一个新项目中分离中间件的概念。
Middleware allows you to define a stack of actions that you should flow through. Express servers themselves are a stack of middlewares.
中间件允许您定义应该流过的一系列操作。Express 服务器本身就是一堆中间件。
// express
var app = express();
// middleware
var stack = middleware();
Then you can add layers to the middleware stack by calling .use
然后你可以通过调用将层添加到中间件堆栈中 .use
// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
next();
});
A layer in the middleware stack is a function, which takes n parameters (2 for express, req& res) and a nextfunction.
中间件堆栈中的一层是一个函数,它接受 n 个参数(2 表示 express,req& res)和一个next函数。
Middleware expects the layer to do some computation, augment the parameters and then call next.
中间件期望该层进行一些计算,增加参数,然后调用next.
A stack doesn't do anything unless you handle it. Express will handle the stack every time an incoming HTTP request is caught on the server. With middleware you handle the stack manually.
除非你处理它,否则堆栈不会做任何事情。每次在服务器上捕获传入的 HTTP 请求时,Express 都会处理堆栈。使用中间件,您可以手动处理堆栈。
// express, you need to do nothing
// middleware
stack.handle(someData);
A more complete example :
一个更完整的例子:
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
})
In express terms you just define a stack of operations you want express to handle for every incoming HTTP request.
用明确的术语来说,您只需定义要为每个传入 HTTP 请求处理的操作堆栈。
In terms of express (rather than connect) you have global middleware and route specific middleware. This means you can attach a middleware stack to every incoming HTTP requests or only attach it to HTTP requests that interact with a certain route.
就快递(而不是连接)而言,您拥有全局中间件和特定于路由的中间件。这意味着您可以将中间件堆栈附加到每个传入的 HTTP 请求,或者仅将其附加到与特定路由交互的 HTTP 请求。
Advanced examples of express & middleware :
快递和中间件的高级示例:
// 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);
});
回答by Barum Rho
After simplifying things, a web server can be seen as a function that takes in a request and outputs a response. So if you view a web server as a function, you could organize it into several pieces and separate them into smaller functions so that the composition of them will be the original function.
简化之后,Web 服务器可以看作是一个接收请求并输出响应的函数。因此,如果您将 Web 服务器视为一个功能,您可以将它组织成几个部分,并将它们分成更小的功能,这样它们的组合就是原始功能。
Middlewares are the smaller functions that you can compose with others and the obvious benefit is that you can reuse them.
中间件是您可以与其他人组合的较小功能,明显的好处是您可以重用它们。
回答by Sergio
I add a late answer to add something not mentioned in the previous answers.
我添加了一个迟到的答案,以添加之前答案中未提及的内容。
By now it should be clear that middleware is/are function(s) run between the client requestand the server answer. The most common middleware functionality needed are error managing, database interaction, getting info from static files or other resources. To move on the middleware stack the next callback must be called, you can see it in the end of middleware function to move to the next step in the flow.
现在应该清楚中间件是在客户端请求和服务器应答之间运行的函数。所需的最常见的中间件功能是错误管理、数据库交互、从静态文件或其他资源中获取信息。要在中间件堆栈上移动,必须调用下一个回调,您可以在中间件函数的末尾看到它以移动到流程中的下一步。
You can use the app.useapproach and have a flow like this:
您可以使用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');
but you can also use another approach and pass each middleware as function arguments. Here is a example from the MooTools Nodejs websitewhere midleware gets the Twitter, Github and Blog flow before the responseis sent back to the client. Note how the functions are passed as arguments in app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. Using app.getwill only be called for GET requests, app.usewill be called for all requests.
但是您也可以使用另一种方法并将每个中间件作为函数参数传递。这是MooTools Nodejs 网站上的一个示例,其中中间件在将 Twitter、Github 和博客流response发送回客户端之前获取。注意函数是如何作为参数传递的app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){。Usingapp.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
});
});
回答by Suraj Jain
expressjs guidehas pretty neat answer to your question, I highly recommend you to read that, I am posting a short snippet of the guide, the guide is quite good.
expressjs指南对您的问题有很好的回答,我强烈建议您阅读该指南,我发布了指南的一小段,该指南非常好。
Writing middleware for use in Express apps
编写用于 Express 应用程序的中间件
Overview
概述
Middlewarefunctions are functions that have access to the request object(req), the response object(res), and the next function in the application's request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.
中间件函数是可以访问请求对象(req)、响应对象(res) 和应用程序请求-响应循环中的下一个函数的函数。下一个函数是 Express 路由器中的函数,它在调用时执行当前中间件之后的中间件。
Middleware functions can perform the following tasks:
中间件功能可以执行以下任务:
- Execute any code.
- Make changes to the request and the response objects.
- End the request-response cycle.
- Call the next middleware in the stack.
- 执行任何代码。
- 对请求和响应对象进行更改。
- 结束请求-响应循环。
- 调用堆栈中的下一个中间件。
If the current middleware function does not end the request-response cycle, it must call next()to pass control to the next middleware function. Otherwise, the request will be left hanging.
如果当前中间件函数没有结束请求-响应循环,则必须调用next()将控制权传递给下一个中间件函数。否则,请求将被挂起。
Example
例子
Here is an example of a simple “Hello World” Express application. The remainder of this article will define and add two middleware functions to the application: one called myLoggerthat prints a simple log message and another called requestTime1that displays the timestamp of the HTTP request.
这是一个简单的“Hello World” Express 应用程序示例。本文的其余部分将定义并向应用程序添加两个中间件函数:一个称为myLogger,用于打印简单的日志消息,另一个称为requestTime 1,用于显示 HTTP 请求的时间戳。
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
Middleware function myLogger
中间件函数 myLogger
Here is a simple example of a middleware function called “myLogger”. This function just prints “LOGGED” when a request to the app passes through it. The middleware function is assigned to a variable named myLogger.
这是一个名为“myLogger”的中间件函数的简单示例。当对应用程序的请求通过它时,此函数仅打印“LOGGED”。中间件函数被分配给名为 myLogger 的变量。
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next()function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next()function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.
注意上面对next()的调用。调用此函数会调用应用程序中的下一个中间件函数。在接下来的()函数不是Node.js的或快递API的一部分,但传递给中间件功能的第三个参数。在接下来的()函数可以被命名为任何东西,但是按照惯例,它总是被命名为“下一个”。为避免混淆,请始终使用此约定。
To load the middleware function, call app.use(), specifying the middleware function. For example, the following code loads the myLoggermiddleware function before the route to the root path (/).
要加载中间件函数,请调用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)
Every time the app receives a request, it prints the message “LOGGED” to the terminal.
每次应用程序收到请求时,它都会向终端打印消息“LOGGED”。
The order of middleware loading is important: middleware functions that are loaded first are also executed first.
中间件加载的顺序很重要:首先加载的中间件函数也最先执行。
If myLoggeris loaded after the route to the root path, the request never reaches it and the app doesn't print “LOGGED”, because the route handler of the root path terminates the request-response cycle.
如果myLogger在路由到根路径之后加载,则请求永远不会到达它并且应用程序不会打印“LOGGED”,因为根路径的路由处理程序终止了请求-响应循环。
The middleware function myLoggersimply prints a message, then passes on the request to the next middleware function in the stack by calling the next()function.
中间件函数myLogger只是打印一条消息,然后通过调用next()函数将请求传递给堆栈中的下一个中间件函数。
- This post will only contain myLogger middleware, for further post you could go to the original expressjs guide here.
- 这篇文章将仅包含 myLogger 中间件,有关进一步的文章,您可以转到此处的原始 expressjs 指南。
回答by Vaibhav Bacchav
=====Very very simple explanation=====
======很简单的解释======
Middlewares are often used in the context of Express.js framework and are a fundamental concept for node.js . In a nutshell, Its basically a function that has access to the request and response objects of your application. The way I'd like to think about it, is a series of 'checks/pre-screens' that the request goes through before the it is handled by the application. For e.g, Middlewares would be a good fit to determine if the request is authenticated before it proceeds to the application and return the login page if the request is not authenticated or for logging each request. A lot of third-party middlewares are available that enables a variety of functionality.
中间件通常用于 Express.js 框架的上下文中,并且是 node.js 的基本概念。简而言之,它基本上是一个可以访问应用程序的请求和响应对象的函数。我想考虑的方式是,请求在被应用程序处理之前经过的一系列“检查/预筛选”。例如,中间件非常适合在请求进入应用程序之前确定请求是否经过身份验证,如果请求未经身份验证或用于记录每个请求,则返回登录页面。有许多第三方中间件可以实现各种功能。
Simple Middleware example:
简单的中间件示例:
var app = express();
app.use(function(req,res,next)){
console.log("Request URL - "req.url);
next();
}
The above code would be executed for each request that comes in and would log the request url, the next() method essentially allows the program to continue. If the next() function is not invoked, the program would not proceed further and would halt at the execution of the middleware.
上面的代码将针对传入的每个请求执行并记录请求 url,next() 方法本质上允许程序继续。如果 next() 函数没有被调用,程序将不会继续执行并且会在中间件执行时停止。
A couple of Middleware Gotchas:
一些中间件陷阱:
- The order of middlewares in your application matters, as the request would go through each one in a sequential order.
- Forgetting to call the next() method in your middleware function can halt the processing of your request.
- Any change the req and res objects in the middleware function, would make the change available to other parts of the application that uses req and res
- 应用程序中中间件的顺序很重要,因为请求将按顺序通过每个中间件。
- 忘记调用中间件函数中的 next() 方法可能会停止处理您的请求。
- 中间件函数中 req 和 res 对象的任何更改都会使使用 req 和 res 的应用程序的其他部分可以使用更改
回答by naz
Middlewares are functions executed in the middle after the input/source then produces an output which could be the final output or could be used by the next middleware until the cycle is complete.
中间件是在输入/源产生输出之后在中间执行的函数,该输出可能是最终输出,也可能被下一个中间件使用,直到循环完成。
It is like a product that goes through an assembly line where it gets modified as it moves along until it gets completed, evaluated or gets rejected.
它就像一个产品通过一条装配线,在那里它会随着它的移动而被修改,直到它被完成、评估或被拒绝。
A middleware expects some value to work on (i.e. parameter values) and based on some logic the middleware will call or not call the next middleware or send a response back to the client.
中间件期望某些值(即参数值)起作用,并且基于某些逻辑,中间件将调用或不调用下一个中间件或将响应发送回客户端。
If you can't still grasp the middleware concept, it is in a way similar to the Decorator or Chain of command patterns.
如果您仍然无法掌握中间件的概念,那么它在某种程度上类似于命令模式的装饰器或链。
回答by rishabh dev
Middleware is a subset of chained functions called by the Express js routing layer before the user-defined handler is invoked. Middleware functions have full access to the request and response objects and can modify either of them.
The middleware chain is always called in the exact order in which it has been defined, so it is vital for you to know exactly what a specific piece of middleware is doing.
Once a middleware function finishes, it calls the next function in the chain by invoking its next argument as function.
After the complete chain gets executed,the user request handler is called.
中间件是在调用用户定义的处理程序之前由 Express js 路由层调用的链式函数的子集。中间件功能可以完全访问请求和响应对象,并且可以修改它们中的任何一个。
中间件链始终按照定义的确切顺序进行调用,因此准确了解特定中间件在做什么对您来说至关重要。
一旦中间件函数完成,它会通过调用其下一个参数作为函数来调用链中的下一个函数。
执行完完整链后,将调用用户请求处理程序。
回答by MNR
Keep things simple, man!
保持简单,伙计!
Note:the answer is related to the ExpressJS builtin middlware cases, however there are different definitions and use cases of middlewares.
注意:答案与 ExpressJS 内置的中间件案例有关,但是中间件有不同的定义和用例。
From my point of view, middleware acts as utility or helper functions but its activation and use is fully optionalby using the app.use('path', /* define or use builtin middleware */)which don't wants from us to write some code for doing very common tasks which are needed for each HTTP request of our client like processing cookies, CSRF tokens and ..., which are very common in most applications so middleware can help us do these all for each HTTP request of our client in some stack, sequence or order of operations then provide the result of the process as a single unit of client request.
在我看来,中间件充当实用程序或辅助函数,但它的激活和使用是完全可选的,app.use('path', /* define or use builtin middleware */)因为我们不希望我们编写一些代码来执行我们客户端的每个 HTTP 请求所需的非常常见的任务像处理 cookie、CSRF 令牌等等,这在大多数应用程序中非常常见,因此中间件可以帮助我们在某些堆栈、序列或操作顺序中为客户端的每个 HTTP 请求完成所有这些操作,然后将过程的结果提供为客户端请求的单个单元。
Example:
例子:
Accepting clients requests and providing back responses to them according to their requests is the nature of web server technology.
接受客户端请求并根据他们的请求向他们提供回复响应是 Web 服务器技术的本质。
Imagine if we are providing a response with just "Hello, world!" text for a GET HTTP request to our webserver's root URI is very simple scenario and don't needs anything else, but instead if we are checking the currently logged-in user and then responding with "Hello, Username!" needs something more than usual in this case we need a middleware to process all the client request metadata and provide us the identification info grabbed from the client request then according to that info we can uniquely identify our current user and it is possible to response to him/her with some related data.
想象一下,如果我们只提供“Hello, world!”的响应。向我们的网络服务器的根 URI 发送 GET HTTP 请求的文本是非常简单的场景,不需要任何其他内容,而是如果我们正在检查当前登录的用户,然后响应“你好,用户名!” 需要比平常更多的东西在这种情况下我们需要一个中间件来处理所有客户端请求元数据并向我们提供从客户端请求中获取的标识信息然后根据该信息我们可以唯一地标识我们当前的用户并且可以响应他/她一些相关的数据。
Hope it to help someone!
希望它可以帮助某人!
回答by Akshay Vinchurkar
In very basic term if i want to explain it like this i learn this from traversymedia youtube channel express crash course.
ok so middle ware is a function who execute after you make a call to your route like this.
在非常基本的术语中,如果我想像这样解释它,我是从 traversymedia youtube 频道速成课程中学到的。
好的,所以中间件是一个在您像这样调用路由后执行的函数。
var logger = function(req, res, next){
console.log('logging...');
next();
}
app.use(logger);
This logger function execute every time you refresh your page that means you can write anything in it that you required to do after your page get rendered any operation api call, reset things basically anything. and put this middleware before your route function order of middleware is really important or it dons't work
每次刷新页面时都会执行此记录器功能,这意味着您可以在页面中编写任何您需要在页面呈现任何操作 api 调用后执行的操作,基本上重置任何内容。并将此中间件放在中间件的路由功能顺序非常重要或不起作用之前


