You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

登录状态下将MongoDB用户记录传递至所有EJS模板问题排查

Got it, let's figure out why your user record isn't making it to all EJS templates. The #1 issue here is almost certainly not handling asynchronous code correctly in your Express middleware—Mongoose queries like Legend.findById() are async, so if you don't wait for them to finish, your template will render before the user data is fetched.

Here's the Fix (Step-by-Step)

First, let's rewrite your middleware to properly handle the async database call. We'll use async/await for readability (callback syntax is included too if you prefer that).

1. Async/Await Middleware (Recommended)

This is the cleanest way to handle async operations in Express middleware:

// Make sure this middleware runs AFTER your session middleware (like express-session)
app.use(async (req, res, next) => {
  // Check if user is logged in via session
  if (req.session.userId) {
    try {
      // Wait for the database query to complete
      const loggedInUser = await Legend.findById(req.session.userId);
      // Attach the user record to res.locals — all EJS templates can access this
      res.locals.currentUser = loggedInUser;
    } catch (err) {
      console.error("Failed to fetch user from DB:", err);
      // Pass errors to Express error handler (don't forget to call next!)
      return next(err);
    }
  } else {
    // If no user is logged in, set currentUser to null for clarity
    res.locals.currentUser = null;
  }
  // Critical: Call next() ONLY after the async operation finishes
  next();
});

2. Callback Syntax Alternative

If you're not using async/await, you need to wrap the query in a callback and call next() inside it:

app.use((req, res, next) => {
  if (req.session.userId) {
    Legend.findById(req.session.userId, (err, user) => {
      if (err) {
        console.error("DB Error:", err);
        return next(err);
      }
      res.locals.currentUser = user;
      next(); // Call next() AFTER fetching the user
    });
  } else {
    res.locals.currentUser = null;
    next();
  }
});

Key Things to Double-Check

  • Session Order: Ensure your session middleware (e.g., express-session) runs BEFORE this user middleware. If req.session is undefined, your userId check will fail.
  • Model Validation: Confirm your Legend model is correctly defined with Mongoose—make sure findById() is a valid method (it should be if you created the model with mongoose.model()).
  • Session Setup: Verify that when users log in, you're actually setting req.session.userId to the correct MongoDB document ID.

Using the Data in EJS Templates

Now you can access currentUser directly in any EJS template:

<% if (currentUser) { %>
  <nav>
    <span>Welcome, <%= currentUser.username %>!</span>
    <a href="/logout">Logout</a>
  </nav>
<% } else { %>
  <nav>
    <a href="/login">Login</a>
    <a href="/signup">Sign Up</a>
  </nav>
<% } %>

The core mistake was likely not waiting for the async findById() call to finish before moving on to render the template—Express doesn't automatically pause for async operations unless you explicitly tell it to with await or callbacks.

内容的提问来源于stack exchange,提问作者Asaf Aviv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:24:51