Search code examples
javascriptnode.jsmongodbkoa

Mongojs query finishing after rendering the page


var list = [];
db.posts.find({}, function(err, docs){
    //console.log(docs);
    list = docs;
});

yield this.render("index", {
    posts: list
});

I have this function for rendering a page after pulling an array of posts from a mongo db. I know it's because of javascript being asynchronous, but I can't seem to get the order right (get array, then render) and the solutions I've seen don't seem to mingle well with koa. How would I code this in order to get the array before the page is rendered?


Solution

  • I don't know what mongodb library you are using, but it seems the library only supports callbacks.

    To program in the synchronous style using yield you must use functions that return promises, thunks, generators etc (as you saw in error message).

    You can either find a mongodb library that supports promises (mongoosejs i think) or you can wrap the library you are using.

    Here are a couple examples of converting your library to a workable format

    // Manually change callback to promise returning function
    var Promise = require('bluebird');
    function find(criteria){
        var deffered, list;
        deffered = Promise.defer();
        db.posts.find(criteria, function(err, results){
            if(err){
                deffered.reject(err);
            }
            else{
                deffered.resolve(result);
            }
        }
        return deffered.promise;
    }
    // in your returning function do something like this
    list = yield find({});
    this.body = yield render('sometemplate', {posts: list});
    
    
    
    // Thunk based solution
    var thunkify = require('thunkify');
    db.posts.find = thunkify(db.posts.find);
    // now db.posts.find() returns a thunk which is yieldable
    list = yield db.posts.find({});
    this.body = yield render('sometemplate', {posts: list});