jeff
jeff

Reputation: 596

Value retrieved from MongoDB is undefined when fetched by Express.js server

Basically what I'm trying to accomplish is pulling the data from a MongoDB database and feed it into my Express.js server. Both of these are ran on the localhost with different addresses. I have tried numerous different methods to get it working and can't seem to get it to work.

Express portion

    app.get('/products', function(request, response) {
    var query = request.query.keywords;
    var promise = new Promise(async (resolve, reject) => {
        var productList = await db.getProducts(query);
        resolve(productList);
    });

    promise.then(function(productList) {
        console.log(productList); // <--- productList is undefined here
        response.json({
            productList
        });     
    }).catch('Error retrieving data');
    // var productList = Promise.resolve(db.getProducts(query));
    // productList.then(products => response.json({products}));
});

MongoDB portion

StoreDB.prototype.getProducts = function(queryParams){
    return this.connected.then(function(db){
        // TODO: Implement functionality
        const collection = db.collection('products');
        var productList;

        if (!queryParams){
            console.log('no queryParams');
            collection.find({}).toArray(function(err, docs) {
            productList = convertToObject(docs);
            // console.log(productList); // <--- productList is defined here
            return productList;
            });
        ////////////

Some extra information: - StoreDB is a functional class with only one property , connected, which is a promise that gets resolved once the connection to the database has been established - The Express.js server calls getProducts which then resolves the promise - Within the getProducts call, productList is defined, but when it returns, the value is undefined

With this being said, I thought that by putting the getProducts within in a promise, it would wait for the function call to be complete, then resolve it. However, that is not the case. Some insights would be greatly appreciated. Thanks.

SOLVED Thanks to @Renan Le Caro

app.get('/products', function(request, response, next) {
  db
    .getProducts(request.query.keywords)
    .then(productList=>response.json({productList}))
    .catch(err=>next(err));
});

StoreDB.prototype.getProducts = function(queryParams){
  return this.connected.then(db => 
    new Promise((resolve, reject) => {
      db
        .collection('products')
        .find({})
        .toArray((err, docs) => err ?  reject(err) : resolve(docs))
    })
}

Upvotes: 0

Views: 247

Answers (2)

IceMetalPunk
IceMetalPunk

Reputation: 5556

getProducts is already a Promise; you shouldn't need to be wrapping a Promise in another Promise, and that just opens the code up to more places things can go wrong. But Promise.resolve does not wait for a Promise to resolve; instead, it IMMEDIATELY returns a new Promise that has already resolved with the value you pass it. That's not what you want. And .catch takes a function to run when the Promise fails, not a string.

Your code should be as simple as this:

app.get('/products', function(request, response) {
  var query = request.query.keywords;
  db.getProducts(query).then(function(productList) {
      console.log(productList);
      response.json({
          productList
      });     
  }).catch(function() {
    response.send('Error retrieving data');
  });
});

Or, if you prefer the async/await syntax:

app.get('/products', async function(request, response) {
  var query = request.query.keywords;
  try {
  const productList = await db.getProducts(query);
      console.log(productList);
      response.json({
          productList
      });     
  } catch (err) {
    response.send('Error retrieving data');
  }
});

Upvotes: 1

Renan Le Caro
Renan Le Caro

Reputation: 365

This is just a promises misuse problem. Here's a fix (not tested).

app.get('/products', function(request, response, next) {
  db
    .getProducts(request.query.keywords)
    .then(productList=>response.json({productList}))
    .catch(err=>next(err));
});

StoreDB.prototype.getProducts = function(queryParams){
  return this.connected.then(db => 
    new Promise((resolve, reject) => {
      db
        .collection('products')
        .find({})
        .toArray((err, docs) => err ?  reject(err) : resolve(docs))
    })
}

Upvotes: 0

Related Questions