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

如何在Mongoose嵌套回调中修改JSON值?解析行为原因

解决Mongoose异步回调中修改数组值不生效的问题

Hey there! Let's break down exactly what's going wrong here and how to fix it—this is a super common gotcha when moving from synchronous languages like C to JavaScript's async model.

为什么你的代码看不到修改后的answer?

The core issue here is asynchronous execution. Mongoose's exec() method doesn't block your code while it talks to the database. Instead, it kicks off the database query and immediately moves on to run the next lines of code:

answer[0].user="asdave" 
answer[0].timeout=1; 
console.log(answer); 
return answer;

By the time the database query finishes and your callback function runs to update answer[0].password, your pwdGen function has already returned the original answer value, and the console.log has already printed it. That's why you always see the "default" password—your callback's changes happen too late.

Also, a quick note on your logic: you had users.length==0 labeled as "exists", which is backwards. An empty array means no superusers exist, so I'll fix that in the solutions below.

解决方案:让代码等待异步操作完成

There are three clean ways to handle this in JavaScript, ordered by how readable they are:

1. 使用Async/Await(最推荐)

Async/await lets you write asynchronous code that looks synchronous, which is probably easier to wrap your head around coming from C. Just mark your function as async and use await to wait for the database query to finish:

async function pwdGen(body) { 
  var answer = [{ error: errors["E004"], user: '', password: 'default', timeout: 0, active: false }]; 
  try {
    // Wait for the database query to complete before moving on
    const users = await user.find()
      .where("usertype").equals("superuser")
      .select("username password")
      .exec();

    // Fix the reversed logic here
    if (users.length === 0) { 
      console.log("empty (no superusers found)"); 
      answer[0].password = "empty_pwd"; 
    } else { 
      console.log("exists (superusers found)"); 
      answer[0].password = "exist_pwd"; 
    }

    // Now we can safely update other fields
    answer[0].user = "asdave";
    answer[0].timeout = 1;

    console.log(answer);
    return answer;
  } catch (err) {
    // Don't forget to handle database errors!
    console.error("Database query failed:", err);
    answer[0].error = err.message;
    return answer;
  }
}

When you call this function, you'll need to use await or .then() to get the result, since it returns a promise:

// Example usage
const result = await pwdGen(yourBodyData);
// OR
pwdGen(yourBodyData).then(result => console.log(result));

2. 使用Promise链式调用

If you're working in an environment that doesn't support async/await (unlikely these days, but possible), you can use Mongoose's built-in promise support with .then():

function pwdGen(body) { 
  var answer = [{ error: errors["E004"], user: '', password: 'default', timeout: 0, active: false }]; 

  // Return the promise chain so callers can handle the result
  return user.find()
    .where("usertype").equals("superuser")
    .select("username password")
    .exec()
    .then(users => {
      if (users.length === 0) { 
        console.log("empty (no superusers found)"); 
        answer[0].password = "empty_pwd"; 
      } else { 
        console.log("exists (superusers found)"); 
        answer[0].password = "exist_pwd"; 
      }

      answer[0].user = "asdave";
      answer[0].timeout = 1;

      console.log(answer);
      return answer;
    })
    .catch(err => {
      console.error("Database query failed:", err);
      answer[0].error = err.message;
      return answer;
    });
}

// Usage
pwdGen(yourBodyData).then(result => console.log(result));

3. 传统回调方式(不推荐)

You could also move all your post-query logic inside the original callback, but this leads to "callback hell" if you add more async operations later. But for completeness:

function pwdGen(body, callback) { 
  var answer = [{ error: errors["E004"], user: '', password: 'default', timeout: 0, active: false }]; 

  user.find()
    .where("usertype").equals("superuser")
    .select("username password")
    .exec(function (err, users) { 
      if (err) {
        console.error("Database query failed:", err);
        answer[0].error = err.message;
        return callback(err, answer);
      }

      if (users.length === 0) { 
        console.log("empty (no superusers found)"); 
        answer[0].password = "empty_pwd"; 
      } else { 
        console.log("exists (superusers found)"); 
        answer[0].password = "exist_pwd"; 
      } 

      answer[0].user = "asdave";
      answer[0].timeout = 1;
      console.log(answer);
      callback(null, answer);
    }); 
}

// Usage
pwdGen(yourBodyData, (err, result) => {
  if (err) {
    // Handle error
  } else {
    console.log(result);
  }
});

额外注意点

  • Mongoose's find() always returns an array (even when no documents match), so checking users.isArray is unnecessary—just use users.length.
  • Always handle errors from database operations! If the query fails (e.g., connection issues), your code needs to catch that instead of crashing.

内容的提问来源于stack exchange,提问作者hendrikschnack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:07:42