3

I have a dashboard view ( dashboard.jade ) that will display two panels with different information, all that info should be retrieved from a database and then sent to the view.

Let's say i have a route file ( document.js ) with two actions defined:

exports.getAllDocuments = function(req, res){
    doc = db.model('documents', docSchema);

    doc.find({}, function(err, documents) {
        if (!err) { 
            // handle success
        }
        else { 
            throw err;
        }
    });
};

exports.getLatestDocumentTags = function(req, res){
    tags = db.model('tags', tagSchema);

    tags.find({}, function(err, docs) {
        if (!err) { 
            // handle success
        }
        else { 
            throw err;
        }
    });
};

These functions would only serve the porpuse of retrieving data from the database.

Now i would like to send that data to the dashboard view from my dashboard.js route file under exports.index function where i render my dashboard view.

The problem is, since the db calls will be async i wouldn't have access to the data before i could call the view.

I guess i could have an action that simply did all my db calls and through callbacks deliver all the data at once to the view but that would make my data retrieval actions not reusable.

I'm really confused on how to tackle this problem correctly, probably i'm getting this async thing all wrong. Can someone give me some hints on how to do this properly ?

mfreitas
  • 2,395
  • 3
  • 29
  • 42

2 Answers2

5

Here's something to pique your interest.

//Check out the async.js library
var async = require('async');

//Set up your models once at program startup, not on each request
//Ideall these would be in separate modules as wel
var Doc = db.model('documents', docSchema);
var Tags = db.model('tags', tagSchema);

function index(req, res, next) {
    async.parallel({ //Run every function in this object in parallel
    allDocs: async.apply(Doc.find, {}) //gets all documents. async.apply will
    //do the equivalent of Doc.find({}, callback) here
    latestDocs: async.apply(Tags.find, {})
    ], function (error, results) { //This function gets called when all parallel jobs are done
      //results will be like {
      //  allDocs: [doc1, doc2]
      //  latestDocs: [doc3, doc4]
      // }
      res.render('index', results);
    });
}
exports.index = index;
};

Try some more tutorials. If you haven't had the "a ha" moment about how async programming works in node, keep going through guided, hand-held tutorials before trying to write brand new programs without guidance.

Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
2
//Check out the async.js library and mangoose model
var mongoOp     =   require("./models/mongo");
var async = require('async');


router.get("/",function(req,res){
    var locals = {};
    var userId = req.params.userId;
    async.parallel([
        //Load user Data
        function(callback) {
             mongoOp.User.find({},function(err,user){
                if (err) return callback(err);
                locals.user = user;
                callback();
            });
        },
        //Load posts Data
        function(callback) {
                mongoOp.Post.find({},function(err,posts){
               if (err) return callback(err);
                locals.posts = posts;
                callback();
            });
        }
    ], function(err) { //This function gets called after the two tasks have called their "task callbacks"
        if (err) return next(err); //If an error occurred, we let express handle it by calling the `next` function
        //Here `locals` will be an object with `user` and `posts` keys
        //Example: `locals = {user: ..., posts: [...]}`
         res.render('index.ejs', {userdata: locals.user,postdata: locals.posts})
    });
vipinlalrv
  • 2,975
  • 1
  • 14
  • 9