How to get res json value in Express.js

4.6k Views Asked by At

I am newbie in node.js. I am trying to do something like this -

I have created one Add To Cart API where i am first checking whether session cart exist or not. If not exist, i am creating new cart via getCartCode(res) method.

app.post('/addToCart', function(req, res) {
console.log('[POST] /addToCart');

var cart = req.body.conversation.memory['cart'];

if(!cart) {
   const response = getCartCode(res);
   console.log("******* Result ************ : " + response.conversation.memory['cart']); // Giving undefined exception here
}
}

getCartCode - This method create cart and return the code which i am returning via res.json

function getCartCode(res)  {

return createCart()
  .then(function(result) {
    res.json({
      conversation: {
        memory: {
          'cart': result,
        }
      }
    });

    return result;
  })
  .catch(function(err) {
    console.error('productApi::createCart error: ', err);
  });
 }

Now what i want is, i want to get cart code in addToCart API in response. I am trying to print cart code in console.log, but it's not printing anything and throwing exception.

2

There are 2 best solutions below

0
On BEST ANSWER

First, you're trying to call a function that returns a Promise, which is asynchronous, and expect it to behave as if it was synchronous, which is not going to work:

// this won't work
const response = getCartCode(res)

function getCartCode(res) {
  return createCart().then(function(result) {
    return {...}
  });
}

You'd have to use something like async/await if you want to be able to use getCartCode similarly to what you're doing right now, like so:

app.post('/addToCart', function(req, res) {
  async function handleAddToCart() {
    // i suggest you use something like the `lodash.get`
    // function to safely access `conversation.memory.cart`
    // if one of these attributes is `undefined`, your `/addToCart`
    // controller will throw an error
    const cart = req.body.conversation.memory.cart

    // or, using `lodash.get`
    // const cart = _.get(req, 'body.conversation.memory.cart', null)

    if (!cart) {
      const response = await getCartCode().catch(err => err)
      // do whatever you need to do, or just end the response
      // and also make sure you check if `response` is an error
      res.status(200).json(response)
      return
    }
    // don't forget to handle the `else` case so that your
    // request is not hanging
    res.status(...).json(...)
  }
  handleAddToCart()
})

function getCartCode() {
  return createCart()
    .then(function(result) {
      return { conversation: { memory: { cart: result } } }
    })
    .catch(function(err) {
      console.error('productApi::createCart error:', err);
      throw err
    })
}

Second, don't pass res to the createCart function. Instead, get the data you need from the createCart function and call res.json inside the /addToCart controller.

Here's how you have to handle this:

app.post('/addToCart', function(req, res) {
  const cart = req.body.conversation.memory.cart

  if (!cart) {
    getCartCode()
      .then(function (result) {
        res.json(result)
      })    
      .catch(/* handle errors appropriately */)
     return;
  }
  // return whatever is appropriate in the `else` case
  res.status(...).json(...);
})

function getCartCode() {
  return createCart()
    .then(function(result) {
      return { conversation: { memory: { cart: result } } }
    })
    .catch(function(err) {
      console.error('productApi::createCart error:', err);
      throw err
    })
}
0
On

res is a writestream. So res.json or res.send will terminate the stream and return the response to client. You just want to return JSON from the getCardCode function. So don't have to send res to getCardCode just return the Promise and await it in the controller.

app.post('/addToCart', async function (req, res) {
  console.log('[POST] /addToCart');

  var cart = req.body.conversation.memory['cart'];
  let response = {}
  if (!cart) {
    response = await getCartCode();
    console.log("******* Result ************ : " + response.conversation.memory['cart']); // Giving undefined exception here
  }
  res.json(response); // terminating the writestream with the response.
});

And here just return the JSON:

function getCartCode() {
  return createCart()
    .then(function (result) {
      return {
        conversation: {
          memory: {
            'cart': result,
          }
        }
      };
    })
    .catch(function (err) {
      console.error('productApi::createCart error: ', err);
    });
}

Note: If createCart returns an error then response.conversation.memory['cart'] this line would throw a cannot find conversation of undefined exception. So you need to handle that in the catch block. Either throw the exception, or return a JSON, or you can add a null check for the response variable.