Node.js同文件函数无法返回值求助(MEAN栈用户创建场景)
问题根源:异步操作的返回值处理错误
嘿,我一眼就看出问题出在哪了——你被Node.js的异步操作特性坑了!
核心问题分析
你的createNewUser函数里,user.save()是异步回调式操作,但你试图在回调函数里return值来作为外层函数的返回结果,这完全行不通:
- 外层的
createNewUser函数在调用user.save()后,会立刻执行完毕(因为异步操作不会阻塞代码),而且函数本身没有任何顶层的return语句,所以默认返回undefined——这就是你两次console.log都输出undefined的原因。 - 你在
user.save()的回调里return的对象,只会成为回调函数自己的返回值,根本不会被外层的createNewUser捕获到。 - 至于你尝试的
setTimeout,它只是延迟了后续代码的执行,但没法改变result一开始就被赋值为undefined的事实——异步操作的结果不会自动同步到这个变量里。
解决方案:用Promise重构异步逻辑
我们需要把createNewUser改造成返回Promise的形式,这样就能正确捕获异步操作的结果。
第一步:重构createNewUser函数
function createNewUser(userData, socialRegistry){ // 返回一个Promise对象 return new Promise((resolve, reject) => { let user; if (socialRegistry){ user = new User({ firstName: userData.firstName, lastName: userData.lastName, email: userData.body.email, googleID: userData.body.provider.ID }); } else { user = new User({ firstName: userData.firstName, lastName: userData.lastName, username: userData.username, password: bcrypt.hashSync(userData.password, 10), email: userData.email, registerDate: new Date() }); } user.save(function(err, savedUser) { if (err) { // 把错误传递给catch reject({ success: false, err: err }); } else { if (socialRegistry){ // 传递社交注册的用户对象 resolve(savedUser); } else { console.log(savedUser); // 传递普通注册的结果对象 resolve({ success: true, obj: savedUser }); } } }); }); }
第二步:修改路由代码处理Promise结果
你可以选择两种方式处理Promise:链式调用.then(),或者更简洁的async/await。
方式一:使用.then()链式调用
router.post('/signup', function(req, res){ createNewUser(req.body) .then(result => { // 区分社交注册和普通注册的返回结果 if (typeof result === 'object' && result.success !== undefined) { res.status(200).json({ message: "successfully created new user", obj: result.obj }); } else { res.status(200).json({ message: "successfully created social user", obj: result }); } }) .catch(err => { res.status(500).json({ message: "unable to create User", obj: err.err }); }); });
方式二:使用async/await(推荐,代码更直观)
router.post('/signup', async function(req, res){ try { const result = await createNewUser(req.body); // 处理返回结果 if (typeof result === 'object' && result.success !== undefined) { res.status(200).json({ message: "successfully created new user", obj: result.obj }); } else { res.status(200).json({ message: "successfully created social user", obj: result }); } } catch (err) { res.status(500).json({ message: "unable to create User", obj: err.err }); } });
额外提示
- 你当前调用
createNewUser(req.body)时没有传递socialRegistry参数,默认会走普通注册分支,这点是正常的;如果要支持Google认证的创建,记得调用时传入true作为第二个参数。 - 以后遇到Node.js异步操作时,一定要记住:回调里的返回值不会影响外层函数,必须用Promise或者async/await来处理异步结果,不能像同步代码那样直接赋值。
内容的提问来源于stack exchange,提问作者tilly
相关产品推荐
相关产品推荐

