-1

Following is my getUser function

const getUsers = async (req, res) => {
    try {
        ddb.get({
            TableName: "Tablename",
            Key: { Username: req.query.username }
        },(err,user) => {
            if(err || Object.keys(user).length === 0) {
                return res.status(404).json("Something went wrong")
            } else {
                const userSociety = Object.keys(user.Item.Societies)[0]
                ddb.get({
                    TableName: "Tablename",
                    Key: { SocietyCode: userSociety }
                },(err, society) => {
                    if(err || Object.keys(society).length === 0) {
                        return res.status(400).json({ message: "Could not fetch society members" })
                    } else {
                        const users = Object.keys(society.Item.SocietyMembers)
                        const usersData = []
                         users.forEach(async u => {
                            ddb.get({
                                TableName: "TestMyMohallaUsers",
                                Key: { Username: u }
                            },async (err,user) => {
                                if(err || Object.keys(user).length === 0) {
                                } else usersData.push({
                                    Username: user.Item.Username,
                                    Firstname: user.Item.Name
                                })
                            })
                        })
                        return res.status(200).json({ message: "Data detched successfully", Users: usersData })
                    }
                })
            }
        })
    } catch (error) {
        return res.status(500).json({ error: "Internal Server Error" })
    }
}

I want to wait for the execution of forEach and then send back the data via return statement but as of now the return statement gives empty array of users.

Clearly my code in not waiting for the execution of forEach and then returning the data. How can I do that someone help me?

Edit: ddb is an instance of DynamoDB

  • You're currently not using promises at all. What is `ddb`? Does its API support promises instead of callbacks? – AKX Sep 15 '22 at 11:08
  • Hello, before diving deeply in the issue, i suggest to mande your code more clear by dividing your blocks into functions, so that you and we can analyse your code more easily and efficiently – sohaieb azaiez Sep 15 '22 at 11:09
  • @David Not a duplicate - there is no async/await in here. – AKX Sep 15 '22 at 11:10
  • @AKX: In the question it states: *"my code in not waiting for the execution of forEach"*. In the code it has: `users.forEach(async u => {` If it's not a duplicate then perhaps the OP could be more specific about the exact problem being observed during debugging? – David Sep 15 '22 at 11:12
  • @David It has `async`, but no `await`, so no promises at all. – AKX Sep 15 '22 at 11:13
  • @AKX ddb is an instance of DynamoDB –  Sep 15 '22 at 11:13
  • @AKX: `ddb.get` *might* return a `Promise`, we don't really know about that. `Promise` or not, it's an asynchronous operation being performed in a `forEach` and not being awaited. – David Sep 15 '22 at 11:14
  • @AKX I just want to iterate through the users array and do a push operation as in my code and return the list. –  Sep 15 '22 at 11:14
  • DynamoDB calls does return promise –  Sep 15 '22 at 11:15
  • @David You can't await on a callback-style async operation. Anyway, now we know it's the AWS DynamoDB API. – AKX Sep 15 '22 at 11:15
  • 1
    Async await in a .forEach never does what you think. Not that you await anyway. Not sure why all those async without a single await – Jaromanda X Sep 15 '22 at 11:23

1 Answers1

1

You'll have a better time if you

  • use the DynamoDB Promise API instead of a pyramid of callbacks
  • refactor your code to a couple of functions
  • Finally, awaiting for all user fetches to complete requires Promise.all for all of those promises.
async function getUser(ddb, username) {
  const user = await ddb
    .get({
      TableName: "TestMyMohallaUsers",
      Key: { Username: username },
    })
    .promise();
  if (!user.Item) {
    throw new Error(`User ${username} not found`);
  }
  return user.Item;
}

async function getSociety(ddb, societyCode) {
  const society = await ddb
    .get({
      TableName: "Tablename",
      Key: { SocietyCode: societyCode },
    })
    .promise();
  if (!society.Item) {
    throw new Error(`Society ${societyCode} not found`);
  }
  return society.Item;
}

const getUsers = async (req, res) => {
  try {
    const user = await getUser(ddb, req.params.username);
    const userSocietyCode = Object.keys(user.Societies)[0];
    const society = await getSociety(ddb, userSocietyCode);
    const societyUsers = Object.keys(society.SocietyMembers);
    const usersData = await Promise.all(
      societyUsers.map(async (member) => {
        const user = await getUser(ddb, member);
        return {
          Username: user.Username,
          Firstname: user.Name,
        };
      }),
    );
    return res
      .status(200)
      .json({
        message: "Data detched successfully",
        Users: usersData,
      });
  } catch (e) {
    return res
      .status(400)
      .json({ message: `Could not fetch information: ${e}` });
  }
};
AKX
  • 152,115
  • 15
  • 115
  • 172