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


当前回答

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.

其他回答

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

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

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

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

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

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

中间件

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

中间件允许您定义应该流经的操作堆栈。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); 
});

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

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.

简单的中间件示例:

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

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

中间件的几个陷阱:

应用程序中中间件的顺序很重要,因为请求将按顺序通过每个中间件。 忘记调用中间件函数中的next()方法可能会中断请求的处理。 中间件函数中req和res对象的任何更改,都将使应用程序中使用req和res的其他部分可用

简单点,伙计!

注意:答案与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.

希望它能帮助到别人!