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

Express+Jade页面加载时偶现数据未定义错误的排查求助

Express.js + PostgreSQL 随机出现"Cannot read properties of undefined (reading 'data')"问题解决

问题根源

你遇到的随机错误本质是异步操作执行顺序混乱:

  • 你发起了三个独立的数据库查询,它们并行执行,没有等待前两个查询完成就触发了第三个查询的回调(调用res.render)。
  • 当第三个查询先执行完毕时,users_list和users_not_in_group_list还未被赋值,仍为undefined。此时模板里访问group_users.data(即undefined.data)就会抛出错误。
  • 另外,模板里的group_users.data是错误用法:users_list是查询返回的rows数组,判断长度应该用length而非data。

修复方案

1. 用Promise.all统一处理并行异步查询

将数据库查询封装为Promise,等待所有查询完成后再渲染页面:

//Create a group detail page
router.get('/details', function (req, res, next) {
  if (req.session.loggedin) {
    const groupName = req.query.group;
    
    // 封装查询为Promise
    const getGroupUsers = () => {
      const userssql = 'select * from "TrustCalendar"."User" where $1 = any ("User"."Groups")';
      return db.pool.query(userssql, [groupName]);
    };

    const getRemainingUsers = () => {
      const users_not_in_group_sql = 'select * from "TrustCalendar"."User" where not $1 = any("User"."Groups")';
      return db.pool.query(users_not_in_group_sql, [groupName]);
    };

    const getGroup = () => {
      const sql = 'select * from "TrustCalendar"."Group" where lower("name") = lower($1)';
      return db.pool.query(sql, [groupName]);
    };

    // 等待所有查询完成后再渲染
    Promise.all([getGroupUsers(), getRemainingUsers(), getGroup()])
      .then(([usersResult, remainingResult, groupResult]) => {
        const users_list = usersResult.rows;
        const users_not_in_group_list = remainingResult.rows;
        const group = groupResult.rows;
        
        res.render('group-detail', {
          group,
          training_hours: group[0].training_hours,
          group_users: users_list,
          remaining_users: users_not_in_group_list
        });
      })
      .catch(error => {
        next(error); // 交给Express错误中间件处理,避免应用崩溃
      });

  } else {
    req.flash('error', 'Please log in!');
    res.redirect('/');
  }
})

2. 修复Jade模板的错误逻辑

修改group_users.data为group_users.length,同时增加空值判断,避免变量未定义时出错:

extends layout

block content
    h1 Group detail overview
    h2 #{group[0].name}

    p 
        a(href="/groups/trainings") Trainings 

    p Head of group
        p #{group[0].head_of_group} 
    p Trainers of #{group[0].name} 
      form(action="/groups/addtrainer?group=" + group[0].name, method="post")
        div add a user to #{group[0].name} 
        if remaining_users && remaining_users.length <= 0
          p All users are already in the group
        else if remaining_users
          select(name="user" multiple='multiple' data-placeholder="Choose user(s)" class="chosen-select" required) 
             each user in remaining_users 
              option(value=user.Name + ' ' + user.LastName) #{user.Name + ' ' + user.LastName } 
        if !group_users || group_users.length <= 0
           p No users in group    
        else 
          each user in group_users 
            p=user.Name + ' ' + user.LastName
            a(href="/groups/removetrainer?group="+group[0].name + '&user_name=' + user.Name + '&user_lname=' + user.LastName) remove trainer 

关键说明

  • 异步操作必须确保所有依赖数据准备完成后再渲染,Promise.all是处理并行异步任务的标准方式。
  • 模板中增加变量存在性判断(如!group_users),可以避免因变量未定义导致的崩溃。
  • 不要直接抛出错误,改用next(error)交给Express错误处理中间件,提升应用稳定性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:05:18