0

I have this request handler on my node server. It has three MongoDB queries, and I want all the results to be returned, before the response is sent.

api.get('/getStats/:productID', (req,res)=>{
  let data = {};
  let dailySales = [];
  let avgProduct = "";
  let customers = [];

  Sales.find({productID: productID}).then(
    sales => {
      dailySales = sales;
    }
  );

  Products.find({}).then(
    products => {
      // Calculate Avg product here
      avgProduct = result;
    }
  );

  Customers.find({}).then(
    customers => {
      customers = customers;
    }
  );

  data = {
    dailySales,
    avgProduct,
    customers
  };

  res.json(data);
});

But running this returns

data: {
  dailySales: [],
  avgProduct: "",
  customers: []
}

i.e. The Mongo response is returning before the data is run. Please how to I fix. Thank You

Kingsley CA
  • 10,685
  • 10
  • 26
  • 39
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Patrick Hund Nov 23 '18 at 15:14
  • Promsies will start resolving After the current script finishes, so you hit res.json() before you found anything in the database. As answered below, use Promise.all() to wait for all the database results to return, then use res.json() inside the .then() handler at the end. – Shilly Nov 23 '18 at 15:15

3 Answers3

5

wait for all the promises to resolve before sending the actual response

const sales = Sales.find({productID: productID});
const allProducts = Products.find({});
const allCustomers = Customers.find({});

Promise.all([sales, allProducts, allCustomers])
 .then(data => res.json(data));  
Karim
  • 8,454
  • 3
  • 25
  • 33
1

you can try using the Promise.all where you can pass the MongoDB queries as parameter to it ,the promise will be resolved when all the queries return the result in the array

ravi
  • 1,127
  • 9
  • 10
0

Try using the in-built util.promisify function along with async-await to get data correctly!

const promisify = require('utils').promisify;

const salesFindOnePromise = promisify(Sales.find);
const productsFindAllPromise = promisify(Products.find);
const customersFindAllPromise = promisify(Customers.find);

findDailySalesByIdAsync = async (productID) => {

    try {
        return await salesFindOnePromise({ productID: productID });
    } catch(err) {
        throw new Error('Could not fetch the appropriate sales with productID');
    }

}

findProductsAsync = async () => {

    try {
        return await productsFindAllPromise({});
    } catch (err) {
        throw new Error('Could not fetch sales!');
    }
}

findCustomersAsync = async () => {

    try {
        return await customersFindAllPromise({});
    } catch (err) {
        throw new Error('Could not fetch customers!');
    }
}


api.get('/getStats/:productID', async (req,res)=>{

try {
  const dailySales = await findDailySalesByIdAsync(productID);
  const avgProduct = await findProductsAsync();
  const customers = await findCustomersAsync();

    const data = {
        dailySales,
        avgProduct,
        customers
    };

    return res.status(200).send(data);

  } catch(err) {
    console.err(`Failed because: {err}`);
    throw new Error('Could not fetch data because of some error!');
  }

});
Kunal Mukherjee
  • 5,775
  • 3
  • 25
  • 53