You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js登录API获取saveUserAccessDetails返回值问题求助

Fixing the Undefined Return Value from 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

  • await for saveUserAccessDetails: Ensures we don't send the response until we have the actual ObjId from the database.
  • async/await instead of nested .then(): Makes the code linear and easier to debug.
  • Fixed logoutTime reference: Now correctly uses req.body.logoutTime in the update operation.
  • Early returns: Uses return to exit the function early if validation fails, avoiding unnecessary code execution.
  • Simplified Promise handling: Removed the redundant new Promise wrapper in login since the function is already async (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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:02:56