Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controller is not able to pass the response to the index.js

I am new to this. There are a couple of solutions posted for a similar problem but none of them helped. I have posted below a very simple toy example that will help you to debug.

index.js

const express = require('express')
port=3001

var controller = require('./controller');
app.use('/api', controller);

controller.js

var model = require('./model')
var router = express.Router();

router.get('/bl', function(req, res) { 
    model.getData( function (err, objects) {
        if(err) return res.send(err);
        return res.status(200).json(objects);
    });
});

module.exports = router;

model.js

const bl = {"hello":"world"}
const getData= (request, response) => {
    return(bl);
  }

module.exports = {
  getData
}

Issue: invoking : http://localhost:3001/api/bl => no response , console : no error

Note:

in my model.js, I am querying in the Postgres database, and I can see the results in console.log.

but I don't see any such result when I try to see data using console.log in controller.js. Similar behavior I observed in the above toy example

like image 716
Monu Avatar asked Jun 07 '20 05:06

Monu


3 Answers

I can see an error and something worrying me.

The error is in following two lines

// In controller.js
model.getData( function (err, objects) {

// In models.js
const getData= (request, response) => {

You define a function accepting two arguments (request, response) (both of them are objects) and than you call it passing only one argument of type function.

The thing worrying me is the getData function itself.

const bl = {"hello":"world"}
const getData= (request, response) => {
  return(bl);
}

Apart from parameters, it is a sync function, but in your question you pointed that in models.js you query in the Postgres database, and you can see the results in console.log; now you give us no details about how you query Postgress, but I suppose you are doing it with something asynchronous (probably pg). The other relevant detail you didn't revealed is if you query Postgress inside or outside the body of getData function. I hope I'm wrong, but since in your example you are returning something define outside the body of the function, I have the doubt.

Let's consider only the good option, you query Postgress inside the body of the function, probably your complete getData function looks like follows.

const getData = (request, response) => {
  client.query('SELECT $1::text as message', ['Hello world!'], (err, res) => {
    // Here you get your message in console
    console.log(err ? err.stack : res.rows[0].message);
    client.end();
  })

  return something;
  // I don't know what, but fore sure something wrong
}

To solve both the problems you just need to fix getData (by chance or by cut&paste you are calling it in the right way in controller.js).

Let's start fixing its signature makeing it accept only one argument: the callback function:

const getData = (done) => {

then let's asynchronously "return" the data we got from Postgress through the done callback function.

const getData = (done) => {
  client.query('SELECT $1::text as message', ['Hello world!'], (err, res) => {
    // We can leave this for debugging purposes
    console.log(err ? err.stack : res.rows[0].message);
    // Here we are not handling errors from client.end()...
    // but we can neglect about this right now
    client.end();
    // Let's calle the callback function passing it the result
    done(err, res);
  })

  // There's nothing to return
}

It should be enough.

Hope this helps.

like image 139
Daniele Ricci Avatar answered Nov 10 '22 08:11

Daniele Ricci


You need a third argument, you will mostly see callback or just cb and execute it in the function and pass some data to it. The first parameter false will be the error argument later and bl will be the objects argument that is passed

const getData= (request, response, callback) => {
    callback(false, bl);
  }

and then pass req and res arguments to it:

model.getData(req, res, function (err, objects) {
    if(err) return res.send(err);
    return res.status(200).json(objects);
});

Or the modern way to do it with async / await you could return an promise

const getData= (request, response) => {
   return new Promise((resolve, reject) => {
      if(someErrorAppear){
         reject("some error occured");
      }
      resolve(bl);
   })
}

Now you can go with async / await

router.get('/bl', async function(req, res) { 
    try {
       let objects = await model.getData(req, res);
       res.status(200).json(objects);
    }catch(err){
       res.send(err);
    }  
    });
});
like image 42
Ifaruki Avatar answered Nov 10 '22 09:11

Ifaruki


There is a simple solution to this.
Actually, the error is in model.js. Try below code:

const bl = {"hello":"world"}
const getData= (callback) => {
    callback (bl)
  }

module.exports = {
  getData
}
like image 45
kartik tyagi Avatar answered Nov 10 '22 08:11

kartik tyagi