如何让函数中的Promise按序执行?解决唯一ID生成校验返回undefined问题
问题分析与修复方案
核心问题
你的generateChatId函数返回undefined、异步逻辑混乱的原因主要有两点:
generateAndCheckIdValid没有返回Promise链,导致await它时拿不到有效结果checkChatIdExists错误处理不完整,且SQL存在注入风险
修复后的代码
function checkChatIdExists(id) { return new Promise((resolve, reject) => { // 用参数化查询避免SQL注入,错误时直接reject con.query("SELECT id FROM messages WHERE id = ?", [id], (err, result)=>{ if(err) { console.log(err); return reject(err); // 错误必须reject,否则Promise会一直pending } resolve(result.length === 0); // 返回布尔值标记ID是否唯一,逻辑更清晰 }) }) } async function generateChatId() { async function generateAndCheckIdValid() { const id = generateId(); // generateId返回同步字符串,无需await console.log("ID generated - " + id); try { const isUnique = await checkChatIdExists(id); if (isUnique) { return id; // ID唯一则直接返回 } else { console.log("ID was not Unique"); return generateAndCheckIdValid(); // 重复就递归重试 } } catch (err) { console.log("数据库查询出错:", err); // 出错时选择重试,也可根据需求抛出错误终止流程 return generateAndCheckIdValid(); } } return generateAndCheckIdValid(); }
关键修改点
checkChatIdExists优化:- 改用参数化查询
?+数组传参,彻底规避SQL注入风险 - 数据库查询出错时主动
reject(err),避免Promise一直处于pending状态 - 直接返回布尔值表示ID是否唯一,逻辑更直观
- 改用参数化查询
generateAndCheckIdValid修复:- 移除不必要的
await(generateId是同步返回字符串) - 用
try/catch替代then/catch,更贴合async函数的写法 - 确保所有分支都有明确返回值:不管ID唯一、重复还是查询出错,都返回结果或递归调用的Promise
- 移除不必要的
generateChatId简化:- 直接返回
generateAndCheckIdValid()的调用结果,无需额外变量中转
- 直接返回
额外建议
如果随机ID碰撞概率较高,可以:
- 优化
generateId算法,结合时间戳、随机数、进程ID等提升唯一性 - 给数据库
messages表的id字段添加唯一约束,双重保障ID唯一性
内容的提问来源于stack exchange,提问作者elliot exists
相关产品推荐
相关产品推荐

