Node.js Mongoose嵌套findOne调用:获取闪卡集合ID并写入JWT
问题解决:登录时正确获取Flashcard Collection ID并存入JWT
问题原因
getCollectionId是异步函数,调用时未等待其执行完成就直接赋值,导致loadedFlashcardCollection是Promise对象而非实际的集合ID,调用toString()后就会显示[object Promise]。
修复方案
将整个登录逻辑改为async/await风格,确保所有异步操作完成后再执行后续代码,同时修复getCollectionId中的错误处理:
//Request email, password -> find user with email -> if no user throw error -> get password -> decrypt and compare -> if false throw error -> if true generate JWT token //JWT secret == JWTSECRETKEY , Expires in 2 hours exports.login = async (req, res, next) => { const email = req.body.email; const password = req.body.password; try { // 1. 查询用户 const loadedUser = await User.findOne({ email: email }); if (!loadedUser) { const error = new Error('A user with this email does not exist'); error.statusCode = 401; throw error; } // 2. 验证密码 const isEqual = await bcrypt.compare(password, loadedUser.password); if (!isEqual) { const error = new Error("Wrong Password"); error.statusCode = 401; throw error; } // 3. 等待获取集合ID(关键:用await等待异步函数完成) const loadedFlashcardCollection = await getCollectionId(loadedUser._id); // 4. 生成JWT令牌 const token = jwt.sign( { email: loadedUser.email, userId: loadedUser._id.toString(), collectionId: loadedFlashcardCollection.toString() }, 'JWTSECRETTOKEN', { expiresIn: '2h' } ); // 5. 返回响应 res.status(200).json({ token: token, userId: loadedUser._id.toString(), collectionID: loadedFlashcardCollection.toString() }); } catch (err) { if (!err.statusCode) { err.statusCode = 500; } next(err); } } // 修复错误处理:未定义的error变量 async function getCollectionId(loadedUserID) { const collection = await flashcardCollection.findOne({ userID: loadedUserID }); if (!collection) { const error = new Error(`No collection found.`); error.statusCode = 401; throw error; } return collection._id; }
核心修改点
- 将
login函数标记为async,用try/catch统一处理异步错误 - 所有异步操作(
findOne、bcrypt.compare、getCollectionId)前添加await,确保拿到实际返回值而非Promise - 修复
getCollectionId中未定义的error变量问题 - JWT payload中字段名改为更清晰的
collectionId(可选,原loadedFlashcardCollection也可)
关键注意事项
异步函数(标记async的函数)调用时,必须通过await或者.then()处理才能拿到最终结果,直接赋值只会得到Promise对象,无法直接使用其返回值。
内容的提问来源于stack exchange,提问作者Zsombor
相关产品推荐
相关产品推荐

