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

基于NodeJS、Express、EJS,如何在内容渲染时显示加载页面?

解决EJS渲染期间无法显示加载页面的方案

当前流程是服务器完成所有数据查询、EJS渲染后才返回完整HTML,导致浏览器一直处于等待状态,无法展示加载反馈。可以通过拆分请求流程来解决:

1. 修改页面路由,先返回带加载动画的基础页面

把原/page路由改成先返回仅包含加载UI和前端请求逻辑的EJS模板,让浏览器立刻收到响应并显示加载状态:

app.get("/page", (req, res) => {
  // 直接返回加载页面,不执行耗时查询
  res.render("loading-page");
});

loading-page.ejs示例:

<!DOCTYPE html>
<html>
<head>
  <title>加载中...</title>
  <style>
    .loading-spinner {
      border: 4px solid #f3f3f3;
      border-top: 4px solid #3498db;
      border-radius: 50%;
      width: 40px;
      height: 40px;
      animation: spin 1s linear infinite;
      margin: 50px auto;
    }
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    #content-area {
      display: none;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
    }
    .error-message {
      color: #dc3545;
      text-align: center;
      display: none;
      margin-top: 20px;
    }
  </style>
</head>
<body>
  <div class="loading-spinner"></div>
  <p style="text-align:center;">正在加载数据,请稍候...</p>
  
  <div id="content-area">
    <!-- 后续通过JS渲染内容 -->
  </div>

  <div class="error-message" id="error">加载失败,请刷新重试</div>

  <script>
    window.onload = async () => {
      const spinner = document.querySelector('.loading-spinner');
      const contentArea = document.getElementById('content-area');
      const errorDiv = document.getElementById('error');

      try {
        // 发起数据请求
        const response = await fetch('/api/page-data');
        if (!response.ok) throw new Error('请求异常');
        
        const data = await response.json();
        
        // 隐藏加载动画,渲染内容
        spinner.style.display = 'none';
        contentArea.style.display = 'block';
        
        // 用JS生成页面内容(可根据实际数据结构调整)
        contentArea.innerHTML = `
          <h1>${data.name}</h1>
          <p>ID:${data.id}</p>
          <p>描述:${data.description}</p>
        `;
      } catch (err) {
        // 显示错误提示
        spinner.style.display = 'none';
        errorDiv.style.display = 'block';
        console.error(err);
      }
    };
  </script>
</body>
</html>

2. 新增API路由处理耗时的数据查询

专门写一个API接口执行原有的数据库查询和数据转换逻辑,返回JSON格式的数据:

app.get("/api/page-data", async (req, res) => {
  try {
    // 执行耗时的数据库查询、数据转换操作
    const data = await fetchDataFromDatabase();
    res.json(data);
  } catch (err) {
    // 捕获错误,返回错误状态码和信息
    res.status(500).json({ error: '数据加载失败' });
  }
});

// 模拟耗时查询函数,替换为你的实际逻辑
async function fetchDataFromDatabase() {
  // 比如用await执行SQL查询、数据处理
  await new Promise(resolve => setTimeout(resolve, 3000));
  return { id: 1, name: "示例数据", description: "这是通过API返回的内容" };
}

3. 额外优化点

  • 添加请求超时处理:避免用户无限等待,超过时间后提示超时
    // 修改前端fetch逻辑,加入超时控制
    window.onload = async () => {
      const spinner = document.querySelector('.loading-spinner');
      const contentArea = document.getElementById('content-area');
      const errorDiv = document.getElementById('error');
    
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 30000); // 30秒超时
    
      try {
        const response = await fetch('/api/page-data', { signal: controller.signal });
        clearTimeout(timeoutId);
        if (!response.ok) throw new Error('请求异常');
        
        const data = await response.json();
        // 渲染逻辑...
      } catch (err) {
        clearTimeout(timeoutId);
        spinner.style.display = 'none';
        if (err.name === 'AbortError') {
          errorDiv.textContent = '加载超时,请刷新重试';
        } else {
          errorDiv.textContent = '加载失败,请刷新重试';
        }
        console.error(err);
      }
    };
    
  • 保留EJS模板能力:如果习惯用EJS语法渲染,可在前端引入EJS库,用前端模板渲染内容
    <!-- 引入前端EJS库 -->
    <script src="https://cdn.jsdelivr.net/npm/ejs@3.1.9/ejs.min.js"></script>
    <!-- 定义EJS模板 -->
    <script type="text/ejs" id="content-template">
      <h1><%= name %></h1>
      <p>ID:<%= id %></p>
      <p>描述:<%= description %></p>
    </script>
    
    <!-- 修改JS渲染部分 -->
    const template = document.getElementById('content-template').innerHTML;
    const renderedHtml = ejs.render(template, data);
    contentArea.innerHTML = renderedHtml;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:26:14