Node.js登录API获取saveUserAccessDetails返回值问题求助
saveUserAccessDetails in Your Login API Hey there! I see exactly what's going on here—your login function is sending the response before saveUserAccessDetails finishes its asynchronous database operation, which is why you're getting undefined for that value. Let's break down the fix step by step.
The Root Cause
saveUserAccessDetails returns a Promise, but you're calling it like a synchronous function without waiting for it to resolve. This means when you run var ObjId = saveUserAccessDetails(...), ObjId is actually a pending Promise, not the resolved document ID—and your res.sendResponse runs immediately, before the Promise finishes.
Step-by-Step Fix
1. Use await to Wait for saveUserAccessDetails
Since your login function is already marked as async, we can use await to pause execution until saveUserAccessDetails resolves with the document ID.
2. Clean Up Promise Nesting (Optional but Recommended)
Your original code uses nested .then() calls, which can get messy. Converting to async/await will make the code easier to read and maintain.
3. Fix Variable References in saveUserAccessDetails
There's a small bug in the logout branch: you're referencing logoutTime directly instead of req.body.logoutTime. Let's fix that too.
Modified Code
Here's the updated version of both functions with all fixes applied:
async function login(req, res, next) { try { const username = req.body.userName; const password = req.body.password; const otp = req.body.otp; const event = req.body.event; const Id = req.body.ObjId; const role = req.body.role; const data1 = {}; // Find active user const data = await UserModel.findOne({ username: username, status: "Active" }); if (!data || !pwdhash.verify(password, data['password'])) { return res.sendResponse(403, false, null, 'Incorrect Username or password'); } // Validate OTP token const usertokenDoc = await UserTokenModel.findOne({ UserId: data._id, Status: "Active", AccessToken: otp }); if (!usertokenDoc) { return res.sendResponse(500, false, null, "OTP hasn't generated for this user."); } // Check OTP expiry const currentTime = new Date(); const tokenCreationTimeUtc = new Date(usertokenDoc.Date.toUTCString() + " UTC"); const difference = Math.max(0, currentTime - tokenCreationTimeUtc); const diffMinutes = Math.floor((difference / 1000) / 60); if (diffMinutes > 3) { return res.sendResponse(500, false, null, "OTP timeout, regenerate the OTP."); } // Generate JWT token const token = jwt.sign( { username: data['username'], user_id: data['_id'] }, config.secret, { expiresIn: config.tokenExpiry } ); // Prepare response data data1.email = data.email; data1.token = token; data1.username = data.username; data1.status = data.status; data1.role = data.role; data1.application = data.application; // Wait for access log to save/get updated const ObjId = await saveUserAccessDetails(req, role, username, event, Id); // Send response only after all async operations are done res.sendResponse(200, true, data1, 'Authentication Successful...' + ObjId); return 'Authentication Successful...' + ObjId; } catch (err) { res.sendResponse(500, false, null, err.toString()); throw err; } } async function saveUserAccessDetails(req, role, name, event, Id) { try { const channel = req.body.channel; const networkDetailsObj = req.body.networkDetails; const userAccessModelData = { "user_name": name, "networkDetails": networkDetailsObj, "loggedIn_systemIp": req.body.loggedInSystemIp, "channel": req.body.channel, "loginTime": req.body.loginTime, "logoutTime": req.body.logoutTime, "name": name, "role": role, "Event_name": event }; if (event === "Logout") { // Update existing log with logout time const accessDoc = await UserAccessLogModel.findOneAndUpdate( { _id: Id }, { $addToSet: { logoutTime: req.body.logoutTime } }, { new: true } ); return accessDoc._id; } else { // Create new access log const userAccessModel = new UserAccessLogModel(userAccessModelData); const logDoc = await userAccessModel.save(); console.log("Access log saved successfully..." + logDoc._id); return logDoc._id; } } catch (err) { console.log("Error while saving access log: " + err); throw err; } }
Key Changes Explained
awaitforsaveUserAccessDetails: Ensures we don't send the response until we have the actualObjIdfrom the database.async/awaitinstead of nested.then(): Makes the code linear and easier to debug.- Fixed
logoutTimereference: Now correctly usesreq.body.logoutTimein the update operation. - Early returns: Uses
returnto exit the function early if validation fails, avoiding unnecessary code execution. - Simplified Promise handling: Removed the redundant
new Promisewrapper inloginsince the function is alreadyasync(async functions return Promises by default).
This should resolve the undefined issue and ensure your login API includes the correct access log ID in the response.
内容的提问来源于stack exchange,提问作者Swapna

