Node.js Express调用userLogin返回undefined问题排查
问题根因
你所有尝试都拿不到值的核心问题有3个:
userLogin本身是普通同步函数,没有任何显式返回值,JS中无return的函数默认返回undefined。你在client.query的回调里写的return signedInDetails,只是回调函数自己的返回值,根本传不到外层userLogin的调用方,相当于你写的return完全没作用到外层。- 你之前试的Promise、async/await写法逻辑完全错了:只是把本来就返回undefined的
userLogin调用结果包了一层,resolve的还是undefined,当然拿不到正确值。setTimeout等2秒更是碰运气,既解决不了函数返回值的问题,也没法保证2秒内查询一定完成,甚至你查询完就调用client.end()关了数据库连接,等再久也没用。 /userSignUp路由里的res.redirect写在了数据库查询回调外面,数据库操作还没跑完就已经返回响应跳转了,就算后续查到值也没地方用。
修复步骤
1. 改造userLogin为异步函数,直接返回Promise结果
不要用回调写法写异步逻辑,改成async/await形式,把查询结果直接return出去:
async function userLogin(cookies){ const HashQuery = { text: 'select * from users where session_id = $1', values: [cookies] } // 等待数据库查询结果,pg客户端v7以上原生支持promise,直接await即可 const res = await client.query(HashQuery); if(res.rows.length === 0){ return false; } // session_id是唯一字段,查询结果最多1条,不需要用map遍历 const targetUser = res.rows[0]; if(parseInt(cookies) === parseInt(targetUser.session_id)){ return { userid: targetUser.user_id, signinstatus: true } } return false; // 删掉原来的client.end(),数据库连接要全局复用,不能查一次就关 }
2. 改造/userSignUp路由,等待所有异步操作执行完再响应
把路由处理函数改成async形式,所有数据库操作、userLogin调用都加await,等所有逻辑走完再执行redirect:
app.post('/userSignUp', async (req, res, next) => { const checkQuery = { text: 'select * from users where user_name = $1', values: [req.body.uName] } const insertQuery = { text: 'INSERT INTO users(f_name, l_name, user_name, password, session_id) VALUES($1, $2, $3, $4, $5)', values: [req.body.fName, req.body.lName, req.body.uName, req.body.pw, req.cookies.hash_an_app] } try { const checkRes = await client.query(checkQuery); if (checkRes.rows.length === 0){ await client.query(insertQuery); // 这里await拿结果,不会再是undefined const abc = await userLogin(req.cookies.hash_an_app); console.log('登录信息:', abc); }else{ console.log("用户名已存在"); } // 所有异步逻辑执行完再跳转 res.redirect('/user/hello') } catch (err) { next(err); // 错误统一交给Express错误中间件处理 } });
额外注意事项
- 绝对不要在单次查询结束后调用
client.end():数据库连接应该在服务启动时初始化一次,全局复用,每次查完就关会导致后续所有数据库请求直接报错。 - 所有依赖异步操作结果的逻辑,必须写在
await之后,不要写到异步回调外面,否则会出现逻辑先执行、异步结果还没返回的时序问题。 - 你原来根路由
app.get('/')里调用userLogin的地方也要加await,否则同样拿不到返回值。
内容的提问来源于stack exchange,提问作者Deke
相关产品推荐
相关产品推荐

