0

I'm new to Node.js and having difficulty working with async/await model. The issue I'm having is with nested function calls returning data in an async/await method, I always get 'undefined'. My functions structure is like this:

const findCustomerOrder = async (id) => {
    const orders = await Order.find({custoemrId:id})
        .then(async (order) => {
            if(order)
                {
                  const products = await findProductsByOrderId(order._id)
                        .then(async (result) => {
                            for(const r in result){
                                console.log("Product ID: ", result._id);
                            }
                        });
                }
            else
                console.log("order not found");     

        });
}

const findProductsByOrderId = async (id) => {
    try{
        const products = await Products.find({orderId:id}, (error, data) => {
            if(error) console.log(error);
            else 
                return data;
        });
    }
    catch(err){
            return 'error!!';
    }
}

I understand that if the top-level call is async/await then all the nested calls should be awaited as well that I've tried to do.

What am I doing wrong here?

0

2 Answers 2

2

Get rid of all the then, and also of the callback in the DB query. Use only await. It will make the whole code a lot easier to reason about and it should also solve your issue as part of the restructuring.

In the example below I also added a loop over the orders, because you are fetching all orders, as array, but then your code was behaving as if it got only one. I also fixed the products loop.

However, the way you fetch products doesn't seem to be right anyway, see my comment below. I didn't fix it because I don't know how your database structure looks, so I don't know what the right way would be.

async function findCustomerOrder (id) {
  const orders = await Order.find({ customerId: id })
  
  for (const order of orders) {
    console.log(`Order ID: ${order._id}`)
    
    const products = await findProductsByOrderId(order._id)
    for (const product of products) {
      console.log(`Product ID: ${product._id}`);
    }
  }
}

async function findProductsByOrderId (id) {
  // Note: I don't think this is right. It seems to find all
  // products with the given ID - which will always be one -
  // and that ID would be the _product_ ID and not the order ID.
  return await Products.find({ _id: id })
}

Preemptive comment reply: The return await is intentional, and this is why.

Sign up to request clarification or add additional context in comments.

5 Comments

Your observation is correct and a typo on my part. Products.find({ _id: id }) } actually reads Products.find({ orderId: id }) }
what are the implications of using for in this context. My understanding is that it is synchronous. What can be an asynchronous equivalent here?
Your function is async. So the loop body (and in fact even the condition, etc.) can be asynchronous as well.
Is for/foreach async safe and will run after async operation is completed in your code sample? Or should I change with something else?
I don't understand the question. There is an await before. Why wouldn't it be safe? (And what would "not safe" even mean?) I think you would get a better feeling for async JavaScript by just playing with it and testing the different scenarios (for example with artificial longer delays).
0

You should remove the then and also the callback and you can do something like below

const findCustomerOrder = async(id) => {
  try {
    const orders = await Order.find({
      custoemrId: id
    });

    if (orders) {
      let promiseArray = [];
      orders.forEach(order => {
        promiseArray.push(findProductsByOrderId(order._id));
      });
      let results = await Promise.all(promiseArray);

      return results;
    }

    return "order not found";
  } catch (err) {
    throw err;
  }
}

const findProductsByOrderId = async(id) => {
  try {
    const products = await Products.find({
      _id: id
    });
    return products;
  } catch (err) {
    throw err;
  }
}

1 Comment

} catch (err) { throw err; } is pretty pointless, don't wrap the code in try altogether

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.