【问题标题】:Express server middleware execute twice?Express 服务器中间件执行两次?
【发布时间】:2019-10-25 03:29:35
【问题描述】:

尝试在索引文件上记录一些数据后。我发现我的快递服务器执行了两次。为什么会出现此错误/错误?

截至本文发布之日,正在运行 Node 12.13.0 LTS、Express 4.17.1 和最新的软件包版本。我尝试过对代码的某些部分进行注释,但似乎总是运行两次。

我的 app.js 代码:

const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const path = require('path');
const bodyParser = require('body-parser');
const favicon = require('serve-favicon');
const app = express();

// ENV Variables
require('dotenv').config();
const PORT = process.env.PORT;

// Authentication Packages
const session = require('express-session');
const passport = require('passport');

// Middlewares
app.use(favicon(path.join(__dirname,'public','images','favicon.ico')));

app.use(bodyParser.urlencoded({extended: false}));
app.use(express.json());

app.use(session({
  secret: 'GBR6N7^?5Xx-Ldqxf&*-Hv$',
  resave: false,
  saveUninitialized: false,
  //cookie: { secure: true }
}));
app.use(passport.initialize());
app.use(passport.session());

// View Engine
app.use(expressLayouts);
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// Routes
app.use('/', require('./routes/index'));

// Controllers
app.use('/profile', require('./routes/profile'));
app.use('/products', require('./routes/products'));
app.use('/bookmarks', require('./routes/bookmarks'));

// Catch 404
app.use((req, res) => {
    res.render('pages/404');
});

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

还有我的 index.js 代码:

const express = require('express');
const router = express.Router();

// Official pages
router.get('/', (req, res) => {

    // THIS IS THE CODE I GET TWICE ON CONSOLE
    console.log(req.user);
    console.log(req.isAuthenticated());
    // THIS IS THE CODE I GET TWICE ON CONSOLE

    res.render('pages/index');
});

router.get('/about', (req, res) => {
    res.render('pages/about');
});

router.get('/features', (req, res) => {
    res.render('pages/features');
});

// Footer pages
router.get('/terms', (req, res) => {
    res.render('pages/terms');
});

router.get('/refunds', (req, res) => {
    res.render('pages/refunds');
});

module.exports = router;

我的 profile.js 上也有这两个功能(用于 passport.js):

passport.serializeUser((userId, done) => {
    done(null, userId);
});

passport.deserializeUser((userId, done) => {
    done(null, userId);
});

我两次得到这些结果:

console.log(req.user);
console.log(req.isAuthenticated());

输出(执行两次!):

undefined
false
undefined
false

我期待一个:

undefined
false

【问题讨论】:

    标签: node.js express


    【解决方案1】:

    由于 Express 路由的工作原理,路径 / 将匹配 //about/favicon.ico 等。这是因为 Express 不仅支持端点路由,还支持路径安装。换句话说,express 支持这样的事情:

    const app = express();
    const route = express.Router();
    
    route.get('/world', (req, res) => { res.send('hello') });
    
    app.get('/hello', route); // mounts world to hello 
                              // so we can access /hello/world
    

    为了支持上述功能,express 需要将/hello 等路径解释为同时表示/hello/hello/anything/else。它需要将其视为端点,并且可能只是通往端点的路径。

    这意味着如果你有一个路径:

    app.get('/', () => {});
    

    如果浏览器请求/favicon.ico,它也会触发。浏览器请求favicon.ico 在浏览器选项卡中绘制小图标。 这就是您的路线被触发两次的原因

    编写 Express 路由/控制器时要记住的几点:

    1. 确保/ 路径位于最后,否则它也会响应对所有其他路径的请求。

    2. 如果您使用的是 express.static(),请确保在 / 路径之前设置它。是的,上面的第一条规则也应该涵盖这一点,但我经常看到这个问题,它值得自己的观点。

    在您的情况下,您可以通过简单地创建一个favicon.ico 图标并将其保存在静态(公共)文件夹中来解决此问题。

    【讨论】:

    • 我认为这仅适用于 app.use(),而不是 app.get()。除了 OP"s app.get('/', ...); 不调用 next() 所以它之后没有更多的路由。
    • 是的,我刚刚通过运行我自己的代码示例确认您的第一段在使用app.get() 时是错误的。 app.get('/', ...)/about 不匹配。
    • 而且,我刚刚确认您在第一段中描述的行为适用于app.use(),而不是app.get()
    • 我在app.js 文件上的这条评论// Middlewares 之后的第一行有一个favicon.ico
    • 我认为是passport.serializeUserpassport.deserializeUser 的问题,但还不确定!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多