2

Hej, have a problem. Trying to send Express response with Mongo data in it.
This is code from my Express server

var Task = require('./modules/Task');
app.get('/get-all-tasks',function(req,res){
    res.setHeader('Content-Type', 'application/json');
    console.log(Task.getAllTasks()); // returns undefined
    res.json({msg:"Hej, this is a test"}); // returns object
});


This is mongoose model in separate file

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/todo-app');

var TaskSchema =  mongoose.Schema({
    name: String,
    assignee: String
},{ collection : 'task' });

var Task = module.exports = mongoose.model('Task', TaskSchema);

module.exports.createTask = function (newTask, callback) {
    newTask.save(callback);

}

module.exports.getAllTasks = function(){
        Task.find().lean().exec(function (err, docs) {
        console.log(docs); // returns json
    });
}

How can I properly send data from getAllTasks function?

lomboboo
  • 1,221
  • 1
  • 12
  • 27

2 Answers2

2

That's looks correct, but your are forgetting about the Javascript's asynchronous behavior :). When you code this:

module.exports.getAllTasks = function(){
        Task.find().lean().exec(function (err, docs) {
        console.log(docs); // returns json
    });
}

You can see the json response because you are using a console.log instruction INSIDE the callback (the anonymous function that you pass to .exec()) However, when you type:

app.get('/get-all-tasks',function(req,res){
    res.setHeader('Content-Type', 'application/json');
    console.log(Task.getAllTasks()); //<-- You won't see any data returned
    res.json({msg:"Hej, this is a test"}); // returns object
});

Console.log will execute getAllTasks() function that doesn't return anything (undefined) because the thing that really returns the data that you want is INSIDE the callback...

So, to get it work, you will need something like this:

module.exports.getAllTasks = function(callback){ // we will pass a function :)
        Task.find().lean().exec(function (err, docs) {
        console.log(docs); // returns json
        callback(docs); // <-- call the function passed as parameter
    });
}

And the we can write:

app.get('/get-all-tasks',function(req,res){
    res.setHeader('Content-Type', 'application/json');
    Task.getAllTasks(function(docs) {console.log(docs)}); // now this will execute, and when the Task.find().lean().exec(function (err, docs){...} ends it will call the console.log instruction
    res.json({msg:"Hej, this is a test"}); // this will be executed BEFORE getAllTasks() ends ;P (because getAllTasks() is asynchronous and will take time to complete)
});
Zalo
  • 642
  • 12
  • 24
1

I believe what you would need to do is return the docs in your getAllTasks function, but perhaps a better way to do it asynchronously using callbacks like so:

module.exports.getAllTasks = function(callback){
        Task.find().lean().exec(function (err, docs) {

        // If there is an error, return the error and no results
        if(err) return callback(err, null)

       // No error, return the docs
        callback(null, docs)
    });
}

And then inside your route you would do:

app.get('/get-all-tasks',function(req,res){
    Task.getAllTasks(err, docs){

      if(err) return res.json(error: err)  
      res.json(msg: docs);    
    }   
});

I'm not sure if getAllTasks should be a mongoose static, in which case your model would look something like this:

TaskSchema.statics.getAllTasks = function (callback) {
  return this.find().lean().exec(callback);
}
Ash
  • 6,483
  • 7
  • 29
  • 37