中间件和app.use在Expressjs中究竟意味着什么?
几乎每个我看到的Express应用程序都有一个中间件的app.use
语句,但是我还没有find关于什么中间件实际上是什么以及app.use
语句正在做什么的清晰简明的解释。 即使是快递公司本身也有点模糊。 你能为我解释这些概念吗?
中间件
在一个新项目中,我将中间件的概念分开了一半。
中间件允许您定义应该stream经的一系列操作。 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
函数。
中间件希望该层做一些计算,增加参数然后再调用。
除非您处理它,否则堆栈不会执行任何操作。 每次在服务器上捕获传入的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 })
用明确的术语来说,你只需定义一个你希望expression的操作栈来处理每个传入的HTTP请求。
在express(而不是连接)方面,你有全局的中间件和路由特定的中间件。 这意味着您可以将中间件堆栈附加到每个传入的HTTP请求,或者仅将其附加到与特定路由交互的HTTP请求。
快递和中间件的高级示例:
// 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服务器可以被看作是接受请求并输出响应的function。 因此,如果您将Web服务器视为一种function,则可以将其组织成多个部分,并将其分解为更小的function,从而使其组成成为原始function。
中间件是您可以与其他人合作的较小function,显而易见的好处是您可以重复使用它们。
我添加了一个迟到的答案,以添加以前的答案中没有提到的东西。
现在应该清楚,中间件是在客户机请求和服务器应答之间运行的function。 所需的最常见的中间件function是错误pipe理,数据库交互,从静态文件或其他资源获取信息。 要在中间件堆栈上移动,必须调用下一个callback函数,您可以在中间件函数的末尾看到它移动到stream程中的下一个步骤。
你可以使用app.use
方法,并有这样的stream程:
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');
但是您也可以使用其他方法并将每个中间件作为函数parameter passing。 下面是MooTools Nodejs网站的一个例子 ,midleware在response
被发送回客户端之前获取Twitter,Github和Blogstream。 注意函数是如何作为parameter passing给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 }); });
中间件是在input/源之后在中间执行的function,然后产生可以是最终输出的输出或者可以被下一个中间件使用直到周期完成。
它就像一个产品,通过一条stream水线经过修改,直到它完成,评估或被拒绝。
中间件期望有一些值可以工作(即参数值),并根据中间件将调用或不调用下一个中间件的某些逻辑或向客户端发回响应。
如果您仍然无法掌握中间件概念,那么它与装饰器或命令模式链相似。
中间件是在调用用户定义的处理程序之前由Express js路由层调用的链接函数的子集。 中间件function可以完全访问请求和响应对象,并可以修改其中任何一个。
中间件链总是按照已定义的顺序进行调用,因此确切知道特定的中间件在做什么是至关重要的。
一旦中间件函数完成,它通过调用其下一个参数作为函数调用链中的下一个函数。
完成链执行后,调用用户请求处理程序。
保持简单,男人!
注意:答案与ExpressJS内置中间件有关,但中间件有不同的定义和用例。
从我的观点来看, 中间件充当实用程序或辅助函数,但其激活和使用完全是可选的,通过使用app.use('path', /* define or use builtin middleware */)
编写一些代码,用于处理客户端的每个HTTP请求所需的非常常见的任务,如处理cookie,CSRF令牌等等,这在大多数应用程序中非常常见, 所以中间件可以帮助我们为每个HTTP请求客户端在某个堆栈中,操作的顺序或顺序,然后将该过程的结果作为单个客户端请求单元提供 。
例:
接受客户请求并根据他们的请求提供回应,这是Web服务器技术的本质。
想象一下,如果我们只是提供一个“你好,世界! 我们的web服务器的根URI的GET HTTP请求文本是非常简单的scheme,不需要任何其他的东西,而是如果我们正在检查当前login的用户,然后用“你好,用户名! 在这种情况下,我们需要比平常更多的东西,我们需要一个中间件来处理所有的客户端请求元数据,并向我们提供从客户端请求中获取的标识信息,然后根据这些信息我们可以唯一地标识我们当前的用户,并且可以响应他/她有一些相关的数据。
希望它能帮助别人!