Search code examples
node.jsmongoosepromiseqbluebird

Q.ninvoke replacement in node bluebird


I'm migration a project from Q to bluebird. In this project Q.invoke is used a lot.

e.g. in central methods like this:

repo.count = function(entity,query)  { // entity is a mongoose model
    var command = query = entity.find(query).count();
    return Q.ninvoke(command, 'exec');
};

What would be the best bluebird way of refactoring this code and returning the same "kind" of promise? Reading the bluebird docs, it seems that promisifyAll seems to be the point in the right direction. Right now I have this which works, but makes the call blocking:

repo.count = function*(entity,query)  {
    entity = bluebird.promisifyAll(entity); // this needs to be moved somewhere central
    return yield entity.find(query).count();
};

Solution

  • Well, there are several things you can do. The most obvious is surprisingly "nothing".

    Mongoose already returns Promises/A+ promises when you don't pass exec its callback, you can just assimilate them:

    repo.count = function(entity,query)  { // entity is a mongoose model
        return entity.find(query).count().exec(); // return promise
    };
    

    You can safely use that promise with Bluebird which will assimilate it gladly:

    Promise.resolve(repo.count(e, q)); // convert to bluebird promise explicitly
    
    someOtherBBPromise.then(function(query){
        return repo.count(entity, query); // `then`able assimilation
    });
    

    That said, it can be desirable to have bluebird promises all-over. For this bluebird has a very robust promisifyAll that lets you promisify mongoose at once:

    var Promise = require("bluebird");
    var mongoose = Promise.promisifyAll(require("mongoose"));
    // everything on mongoose promisified 
    someEntity.saveAsync(); // exists and returns bluebird promise