Express.js中预约数据发送报错,请求排查控制器代码问题
代码中的错误及修正方案
核心错误点
- SQL注入风险:直接用字符串拼接
${req.query.availableInstructor}构建SQL语句,极易遭注入攻击,必须改用参数化查询。 - 查询字段缺失:JOIN了
instructor表但未选取该表的name、avatar等字段,导致后续代码中element.instructor相关属性完全无法获取。 - 对象属性引用错误:查询结果是扁平的字段集合(如
instructor_id、day_id),并非嵌套的instructor/day对象,代码里element.instructor.id、element.day.name这类写法完全错误。 - 重复键与无效赋值:
avatar: element.instructor, avatar,存在重复的avatar键,且element.instructor不存在,赋值无意义。 - 连接池误用:
finally中调用pool.end()会直接关闭整个数据库连接池,后续所有数据库操作都会失败,连接池无需手动关闭,查询完成后连接会自动归还池。 - 错误处理不完整:仅在控制台打印错误,未向客户端返回错误响应,前端无法感知请求失败。
- 逻辑判断无效:
if (element.instructor)判断的对象不存在,内部代码永远不会执行,且逻辑意图混乱。
修正后的代码示例
pool .query( `SELECT available_instructor.id, available_instructor.instructor_id, available_instructor.day_id, available_instructor.time, instructor.name AS instructor_name, instructor.avatar AS instructor_avatar, day.name AS day_name FROM available_instructor JOIN instructor ON instructor.id = available_instructor.instructor_id JOIN day ON day.id = available_instructor.day_id WHERE available_instructor.instructor_id = $1;`, [req.query.availableInstructor] // 参数化查询,避免注入 ) .then((result) => result.rows) .then((availableSchedules) => { // 按讲师ID组织日程数据(适配预约场景需求) const availableScheduleObj = {}; availableSchedules.forEach((item) => { const instructorId = item.instructor_id; // 初始化讲师基础信息 if (!availableScheduleObj[instructorId]) { availableScheduleObj[instructorId] = { id: instructorId, name: item.instructor_name, avatar: item.instructor_avatar, schedules: [] }; } // 添加该讲师的可用时段 availableScheduleObj[instructorId].schedules.push({ day_id: item.day_id, day_name: item.day_name, time: item.time }); }); res.json(availableScheduleObj); // 返回整理后的结构化数据 }) .catch((err) => { console.log("err", err); res.status(500).json({ error: "获取可用预约信息失败" }); // 向前端返回错误提示 }); // 移除pool.end(),连接池无需手动关闭
额外说明
- 修正后的SQL通过
$1占位符和参数数组实现参数化查询,彻底规避注入风险。 - 补充查询
instructor表的关键字段,并通过别名区分避免字段冲突。 - 重新梳理数据结构,按讲师ID分组存储其所有可用日程,符合预约场景的常用数据格式。
- 完善错误响应逻辑,确保前端能及时处理请求失败的情况。
内容的提问来源于stack exchange,提问作者Niko
相关产品推荐
相关产品推荐

