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

客户端与服务端数据已更新但渲染未同步(Nodejs/Express/MySQL/EJS)

Fixing Stale Data Rendering with Async MySQL Queries in Express

Hey there, I see exactly what's going on here—your issue boils down to asynchronous JavaScript execution order, which is super common when working with database queries in Node.js. Let's break it down and fix this step by step.

The Root Problem

Your connection.query() call is asynchronous—it runs in the background while the rest of your code continues to execute. Right now, you're calling res.render() immediately after triggering the query, before the database has actually returned the new posts data. That means your template is rendering with the old value of the posts variable (from a previous request, or undefined if it's the first run).

Here's the actual execution order of your current code:

  1. Trigger the database query (it starts running in the background)
  2. Call res.render() with the current stale posts value
  3. Log posts (still stale)
  4. Later the query finishes and updates posts—but it's too late, the response already went out to the client!

The Fixed Code

Move your res.render() (and any logic that depends on the query result) inside the query callback, so it only runs after you have the fresh data from the database:

app.get("/" + element.name, function(req, res){ 
  connection.query(`SELECT * FROM sub${element.name}posts`, function(error, result) { 
    if(error) { 
      console.log(`Database error:`, error); // Log the actual error for debugging
      return res.status(500).send("Failed to load posts"); // Let the client know something went wrong
    } 
    // Now we have fresh data—render the page with it
    console.log(`Successfully fetched posts!`);
    res.render("sub" + element.name, {posts: result});
    console.log(result + " Here");
  }); 
});

Key Improvements

  • No more stale data: The render only happens once we have the fresh result from the database
  • Proper error handling: We send an error response to the client instead of just logging to the console
  • Eliminated global variable risk: Using result directly avoids race conditions where concurrent requests might overwrite a global posts variable

Bonus: Clean Up with Async/Await

If you want to avoid callback nesting and make your code more readable, wrap the query in a promise and use async/await:

// First, wrap connection.query in a promise (you can define this once in your codebase)
const queryPromise = (sql) => {
  return new Promise((resolve, reject) => {
    connection.query(sql, (error, result) => {
      if (error) reject(error);
      else resolve(result);
    });
  });
};

// Then use async/await in your route handler
app.get("/" + element.name, async function(req, res){ 
  try {
    const posts = await queryPromise(`SELECT * FROM sub${element.name}posts`);
    console.log(`Successfully fetched posts!`);
    res.render("sub" + element.name, {posts});
    console.log(posts + " Here");
  } catch (error) {
    console.log(`Database error:`, error);
    res.status(500).send("Failed to load posts");
  }
});

This makes the code flow linearly, which is easier to read and debug as your app grows.

内容的提问来源于stack exchange,提问作者Jess Merberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:10:55