我看到的几乎每个Express应用程序都有一个app.use语句用于中间件,但我还没有找到一个清晰、简洁的解释来说明中间件到底是什么以及app.use语句在做什么。甚至express文档本身在这一点上也有点模糊。你能给我解释一下这些概念吗?
当前回答
简单点,伙计!
注意:答案与ExpressJS内置中间件用例有关,但是中间件有不同的定义和用例。
From my point of view, middleware acts as utility or helper functions but its activation and use is fully optional by 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.
例子:
接受客户端请求并根据他们的请求提供响应是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.
希望它能帮助到别人!
其他回答
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服务器本身就是一堆中间件。
// 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的高级示例:
// 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网站的例子,中间件在响应被发送回客户端之前获得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
});
});
expressjs的指南非常简洁地回答了你的问题,我强烈建议你去阅读,我发布了一个简短的指南片段,指南是相当好的。
编写用于Express应用程序的中间件
概述
中间件函数是能够访问请求对象(req)、响应对象(res)以及应用程序请求-响应周期中的下一个函数的函数。下一个函数是Express路由器中的一个函数,当它被调用时,执行当前中间件之后的中间件。
中间件函数可以执行以下任务:
执行任何代码。 对请求和响应对象进行更改。 结束请求-响应循环。 调用堆栈中的下一个中间件。
如果当前中间件函数没有结束请求-响应周期,它必须调用next()将控制传递给下一个中间件函数。否则,请求将被挂起。
例子
下面是一个简单的“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()函数将请求传递给堆栈中的下一个中间件函数。
这篇文章将只包含myLogger中间件,对于更多的文章,你可以去原始的expressjs指南这里。
推荐文章
- 将Node.js配置为记录到文件而不是控制台
- 中间件和app.use在Expressjs中是什么意思?
- 当使用ES6模块时,Node.js中的__dirname的替代方案
- 在Node.js中读取文件
- DeprecationWarning:当我将脚本移动到另一个服务器时,由于安全性和可用性问题,Buffer()已弃用
- 我如何确定正确的“max-old-space-size”为Node.js?
- npm犯错!代码UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- Access-Control-Allow-Origin不允许Origin < Origin >
- 如何获得所有已注册的快捷路线?
- 你可以为你的组织托管一个私有的存储库来使用npm吗?
- 如何定位父文件夹?
- Gulp命令未找到-安装Gulp后错误
- 在Node.js中写入文件时创建目录
- 如何将自定义脚本添加到包中。Json文件,运行javascript文件?
- 使用child_process。execSync但保持输出在控制台