Grofit Grofit - 2 months ago 15
Javascript Question

Mongodb node driver 2.0.* with Bluebird 2.9.* promisification

So there are a few other queries around this subject such as:
How can I promisify the MongoDB native Javascript driver using bluebird?

However it does not seem to address the latest version of the driver, which seems to have issues when trying to promisify. Currently I can get the

MongoClient
working by doing:

Promise.promisifyAll(mongodb.MongoClient); // Using .Prototype here fails to promisify


However no matter what I try the Collections do not seem to operate using the
*async
calls, it may invoke them but they never get resolved or rejected so they just hang in limbo.

Historically in the previous versions you would just
Promise.promisifyAll(mongodb)
and you were done, but I am unsure as to how to correctly handle this in the new driver.

Here is an example output of a collection which has been created using the mongo direct promisification
connectAsync
then getting the collection from the returned db. Once I try to do anything on the collection it just hangs and promises dont return from it:


{ s:
{ pkFactory:
{ [Function: ObjectID]
index: 14727641,
createPk: [Function: createPk],
createFromTime: [Function: createFromTime],
createFromHexString: [Function: createFromHexString],
isValid: [Function: isValid],
ObjectID: [Circular],
ObjectId: [Circular],
createPkAsync: [Object],
createFromTimeAsync: [Object],
createFromHexStringAsync: [Object],
isValidAsync: [Object],
bindAsync: [Object],
toStringAsync: [Object],
callAsync: [Object],
applyAsync: [Object],
lazyAsync: [Object],
throttleAsync: [Object],
debounceAsync: [Object],
delayAsync: [Object],
everyAsync: [Object],
cancelAsync: [Object],
afterAsync: [Object],
onceAsync: [Object],
fillAsync: [Object] },
db:
{ domain: [Object],
_events: {},
_maxListeners: undefined,
s: [Object],
serverConfig: [Getter],
bufferMaxEntries: [Getter],
databaseName: [Getter],
options: [Getter],
native_parser: [Getter],
slaveOk: [Getter],
writeConcern: [Getter] },
topology:
{ domain: [Object],
_events: [Object],
_maxListeners: undefined,
connectTimeoutMS: 500,
s: [Object],
bson: [Getter],
isMasterDoc: [Getter],
poolSize: [Getter],
autoReconnect: [Getter],
host: [Getter],
port: [Getter],
emitOpen: false,
socketTimeoutMS: 0 },
dbName: 'some-db-name',
options: {},
namespace: 'some-namespace',
readPreference: null,
raw: undefined,
slaveOk: false,
serializeFunctions: undefined,
internalHint: null,
collectionHint: null,
name: 'some-collection-name' } }

Answer

You can promisify it directly after requiring, as exemplified on bluebird API docs, like this:

var Promise = require("bluebird");
var MongoDB = Promise.promisifyAll(require("mongodb"));
var util = require('util');

console.log(util.inspect(MongoDB, { showHidden: true }));

Using bluebird 2.9.14 and mongodb driver 2.0.22, I got this (simplified) results:

  // ....
  Collection: 
   { [Function]
     [length]: 6,
     [name]: '',
     [arguments]: [Getter/Setter],
     [caller]: [Getter/Setter],
     [prototype]: 
      { [constructor]: [Circular],
        collectionName: [Getter],
        // .... 
        findAsync: [Object],
        insertOneAsync: [Object],
        insertManyAsync: [Object],
        bulkWriteAsync: [Object],
        insertAsync: [Object],
        updateOneAsync: [Object],
        replaceOneAsync: [Object],
        updateManyAsync: [Object],
        updateAsync: [Object],
        deleteOneAsync: [Object],
        removeOneAsync: [Object],
        deleteManyAsync: [Object],
        removeManyAsync: [Object],
        removeAsync: [Object],
        saveAsync: [Object],
        findOneAsync: [Object],
        // ....

And queried successfully like this:

MongoDB.connectAsync('mongodb://localhost:27017/test').then(function(db) {
    return db.collection("orders").findOneAsync({});
}).then(function(orders) {
    console.log(orders);
}).catch(function(err) {
    console.log(err);
});

UPDATE

Using the MongoClient object works as well:

var Promise = require("bluebird");
var MongoDB = Promise.promisifyAll(require("mongodb"));
var MongoClient = Promise.promisifyAll(MongoDB.MongoClient);

MongoClient.connectAsync('mongodb://localhost:27017/test').then(function(db) {
    return db.collection("orders").find({}).toArrayAsync();
}).then(function(orders) {
    console.log(orders)
}).catch(function(err) {
    console.log(err);
});