Search code examples
javascriptnode.jsmongodbpromisebluebird

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' } }


Solution

  • 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);
    });