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

如何通过回调返回值?数据库查询回调处理问题技术求助

Fixing Asynchronous Callback Issues in Your Database Query Code

It looks like you're running into a common pitfall with asynchronous JavaScript code—your nbr_users function isn't returning the value you expect because the database query runs in the background, and the callback's return doesn't propagate back to the function's caller. Let's break down the problem and fix it step by step.

The Root Cause

Your current nbr_users function uses a callback to handle the database response, but callbacks are asynchronous. When you call nbr_users(key), it immediately returns undefined (since there's no top-level return statement in the function) before the database query finishes. The return users.length inside the callback only returns a value to the callback's invoker (the database library), not to your code that calls nbr_users.

Solution: Use Promises & Async/Await

Modern JavaScript provides cleaner ways to handle asynchronous code with Promises and async/await. Here's how to refactor your code:

Step 1: Rewrite nbr_users to Return a Promise

First, update nbr_users to return a Promise that resolves with the user count, or rejects with an error:

// Option 1: Explicit Promise wrapper (works with any callback-based db library)
const nbr_users = (key) => {
  return new Promise((resolve, reject) => {
    db.User.find({ shop: key }, (err, users) => {
      if (err) {
        reject(err); // Pass error to the caller
      } else {
        resolve(users.length); // Pass the user count to the caller
      }
    });
  });
};

// Option 2: Async/await shortcut (if your db library supports Promises, like Mongoose)
const nbr_users = async (key) => {
  const users = await db.User.find({ shop: key });
  return users.length;
};

Step 2: Use Async/Await in Your Request Handler

Now, modify your exported request handler to be async, so you can await the user count for each account:

module.exports = async (req, res) => {
  try {
    // Fetch all accounts first
    const accounts = await db.Account.find({});
    const accountMap = {};

    // Process each account and get its user count
    for (const account of accounts) {
      // Wait for the user count to be retrieved
      const userCount = await nbr_users(account.shop); // Adjust the key to match your account structure
      // Add the account and user count to your map
      accountMap[account._id] = { ...account.toObject(), userCount };
    }

    // Send the final map as the response
    res.json(accountMap);
  } catch (err) {
    // Handle any errors that occur during the process
    res.status(500).json(err);
  }
};

Bonus: Parallelize Queries for Better Performance

If you have many accounts, processing them one by one with a for...of loop can be slow. Use Promise.all to run all user count queries in parallel:

module.exports = async (req, res) => {
  try {
    const accounts = await db.Account.find({});
    
    // Create an array of promises to fetch user counts for all accounts
    const accountPromises = accounts.map(async (account) => {
      const userCount = await nbr_users(account.shop);
      return { [account._id]: { ...account.toObject(), userCount } };
    });

    // Wait for all promises to resolve
    const accountResults = await Promise.all(accountPromises);
    
    // Combine results into a single map
    const accountMap = Object.assign({}, ...accountResults);

    res.json(accountMap);
  } catch (err) {
    res.status(500).json(err);
  }
};

Why This Works

  • Promises let us wrap asynchronous operations and handle their results later.
  • Async/await makes asynchronous code read like synchronous code, making it easier to follow and debug.
  • Proper error handling with try/catch ensures any database errors are caught and sent back in the response.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:07:37