VrxVedant
VrxVedant

Reputation: 35

Can't push object into the array after running mongodb query

I was trying to set up the logic for adding some items into an array, which id's express server receives from a client. My program receives the id of the product and then I was fetching the product details from MongoDB query findOne, and then with some customized details I used to push that item into an array but it's not working, whenever I try to push any element after MongoDB query it's not working, I don't know why, but please help me, Sorry for my bad English !

It's an ExpressJS server using MongoDB

Items received: (But it is actually received from the client in the form of JSON) :

const items= [
        {
            productId:"61e01e7e24612b56c33b06c3",
            quantity:"4"
        },
        {
            productId:"61e01e9024612b56c33b06c6",
            quantity:"10"
        }
    ]

The actual code here is the problem

let itemsData = [];
items.forEach(async (item) => {
    const itemData = await findProduct({ _id: item.productId });

    // Check if product found
    if (!itemData) return res.status(400).json({ message: "Product is Invalid" });

    // If found add that in object
    itemsData.push({
        productId: itemData._id,
        name: itemData.name,
        price: itemData.price,
        quantity: item.quantity,
        unit: "Nos",
        totalPrice: parseInt(itemData.price) * parseInt(item.quantity)
    });
});

The code above doesn't push that object into the itemsData array

findProduct Function

// Service to find Product
async findProduct(filter) {
    return await ProductModel.findOne(filter);
}

If I used that push method and tried only to itemsData.push("hello"); before the MongoDB query it works, but if I put it after the findProduct Query it doesn't work! I don't know what is wrong with it! Somebody help me!

I just want to push those items with detail into itemData object happily which is not happening I tried to console.log(itemsData) it just return [], what should I do?

Upvotes: 0

Views: 760

Answers (2)

Nacho
Nacho

Reputation: 69

Try using For Of instead of forEach (don't forget to add async)

  let itemsData = [];
  
  for (const item of items) {
    const itemData = await findProduct({ _id: item.productId });
    
    // Check if product found
    if (!itemData) return res.status(400).json({ message: "Product is Invalid" });
    
    // If found add that in object
    itemsData.push({
        productId: itemData._id,
        name: itemData.name,
        price: itemData.price,
        quantity: item.quantity,
        unit: "Nos",
        totalPrice: parseInt(itemData.price) * parseInt(item.quantity)
    });
  }

Upvotes: 1

Eduardo
Eduardo

Reputation: 425

It's because forEach function is not designed to work well with async calls.

You could use map instead.

This should work:

let itemsData = [];

const promises = items.map(async (item) => {
 const itemData = await findProduct({ _id: item.productId });

 // Check if product found
 if (!itemData) return res.status(400).json({ message: "Product is Invalid" });

 return {
  productId: itemData._id,
  name: itemData.name,
  price: itemData.price,
  quantity: item.quantity,
  unit: "Nos",
  totalPrice: parseInt(itemData.price) * parseInt(item.quantity)
 };
});

itemsData = await Promise.all(promises);

When you use map with async, you will have an array of promises, so you can use Promise.all to wait for the values to get resolved.

Check this out for more details.

Upvotes: 0

Related Questions