Javascript 为什么我的中间件执行了两次?

Javascript 为什么我的中间件执行了两次?,javascript,node.js,express,middleware,Javascript,Node.js,Express,Middleware,我在express.js/node.js中编写了一个中间件,用于检查会话,并检查会话是否找到用户ID,显示用户的菜单,或者默认菜单 每个页面请求都会检查id并从数据库中获取用户数据(id、名称、类别等) 以下是中间件: module.exports = function(req,res,next){ console.log("INSIDE SESSION HANDLER"); if(!req.session.uid) return next(); else{

我在express.js/node.js中编写了一个中间件,用于检查会话,并检查会话是否找到用户ID,显示用户的菜单,或者默认菜单

每个页面请求都会检查id并从数据库中获取用户数据(id、名称、类别等)

以下是中间件:

module.exports = function(req,res,next){
    console.log("INSIDE SESSION HANDLER");

    if(!req.session.uid) return next();
    else{   
        User.get(uid, function(user){
            if (!user) {return next(err);}
            else{
                req.user = res.locals.user = user;
                next();
            }
        })
    }
}
然后,ejs检查局部变量,如果有ID,则显示用户的菜单

我正在加载一个测试页面,我没有使用socket.io库,但忘记删除

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %> , <%= settings.title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
    <script src="/socket.io/socket.io.js"></script>//<== SHOULD DELETE THIS
    <h1>Login</h1>
        <%include menu%> //<== USES EJS TO CHECK LOCALS AND SHOW DEFAULT OR USER MENU
  </head>
  <body>
我想真正了解请求/响应和中间件。那么为什么会发生这种情况呢?为什么这个中间件会因为404错误而执行两次?404错误响应是否会导致中间件执行两次

谢谢

编辑

我使用app.js中的中间件,如下所示:

app.use(favicon(__dirname + '/node_modules/static-favicon/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({resave:'false', saveUninitialized:'false', secret:'secret'}));

app.use(express.static(path.join(__dirname, 'public')));
app.set('multimedia', __dirname + '/public/multimedia');

app.use(handler); //<= THE MIDDLEWARE IN QUESTION


app.use(messages);
app.get('/', routes.list);
app.get('/register', register.form);
app.post('/register', register.submitit);
app.use(favicon(uu dirname+'/node\u modules/static favicon/favicon.ico');
应用程序使用(记录器(“开发”);
use(bodyParser.json());
use(bodyParser.urlencoded({extended:false}));
使用(cookieParser());
使用(会话({resave:'false',saveUninitialized:'false',secret:'secret'}));
app.use(express.static(path.join(uu dirname,'public'));
app.set('multimedia','u dirname+'/public/multimedia');

应用程序使用(处理程序)// 你在哪里应用这个中间件

例如,如果你有

app.use(handler)
如果
处理程序
的形式为
函数(req、res、next)
,则它将应用于每个请求(使用任何HTTP动词)。或者

app.get('/some/route', handler)
其中
处理程序
将应用于
/some/route
下面的任何地方(例如
/some/route/any/deepness

因此,我的猜测是,您过度应用了中间件功能(我正在交换处理程序和中间件,它们具有相同的函数签名-也许处理程序更适合于向调用
next()
的人发送响应和中间件的函数)。但是很难说没有这个中间件是如何应用的

请参阅和Express提供的其他指南


另外,您不需要在中间件中
返回next()
。只需
next()

中间件运行两次的原因是,它运行一次用于初始请求,一次用于404(不存在的静态脚本)

如果
express.static
可以找到一个文件,它将发送相应文件的响应,如果找不到正确的文件(就像您的情况一样),它将调用
next()
,尝试将请求与其他路由匹配,运行下面定义的任何其他中间件
express.static

换句话说,如果
express.static
确实找到了要提供服务的文件,那么它下面的中间件将不会运行。在您的情况下,中间件为实际请求运行一次,并尝试查找文件或正确的路由作为响应

这可以通过记录正常静态文件和不存在的静态文件的
req.path
来观察:

app.js-

app.use(express.static(path.join(__dirname, 'public')));

app.use(function(req, res, next){
  console.log('Requested path: %s', req.path);
  next();
})
layout.hbs(为“/”呈现)-


希望这能有所帮助。

我更新了我的问题,展示了如何在
app.js
中定义中间件。很好的回答,我明白你的意思,但我不认为我用得太多,因为我定义了它,然后它后面的其他定义都使用了它。这与404错误和中间件执行两次有什么关系?Thanks@slevin当您请求不存在的文件时,中间件会运行(因为它运行在非静态的所有文件上),然后是打印404页面的404处理程序。可能是
express.static
无法为请求的文件提供服务,因此它会继续请求链(也称为“
next()
”),在这种情况下,它将运行
app.use(handler)
中间件,并尝试与下面的其他路由匹配,没有一个路由适用,因此它显示404。换句话说,它记录了一次实际的页面加载,一次记录404。在测试了这种情况后,我在下面的回答中写了上面的评论。非常感谢您的回答。我猜在第三段的第一行中,
对文件是否有好处
您的意思是
是否找到了文件
app.use(express.static(path.join(__dirname, 'public')));

app.use(function(req, res, next){
  console.log('Requested path: %s', req.path);
  next();
})
<!DOCTYPE html>
<html>
  <head>
    <title>{{title}}</title>
    <link rel='stylesheet' href='/stylesheets/style.css' /> <!-- exists -->
    <link rel='stylesheet' href='/stylesheets/foo.css' /> <!-- doesn't exist -->
  </head>
  <body>
    {{{body}}}
  </body>
</html>
Requested path: /
Requested path: /stylesheets/foo.css