如何使用bluebird宣传MongoDB本机Javascript驱动程序?

时间:2014-05-20 23:58:19

标签: javascript mongodb promise bluebird node-mongodb-native

我想将MongoDB native JS driverbluebird promises一起使用。如何在此库中使用Promise.promisifyAll()

5 个答案:

答案 0 :(得分:23)

2.0分支文档包含更好的宣传指南https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification

它实际上有mongodb示例,它更简单:

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

答案 1 :(得分:18)

使用Promise.promisifyAll()时,如果必须实例化目标对象,则有助于识别目标原型。对于MongoDB JS驱动程序,标准模式是:

  • 使用Db静态方法或MongoClient构造函数
  • 获取Db个对象
  • 致电Db#collection()以获取Collection个对象。

所以,借用https://stackoverflow.com/a/21733446/741970,你可以:

var Promise = require('bluebird');
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var Collection = mongodb.Collection;

Promise.promisifyAll(Collection.prototype);
Promise.promisifyAll(MongoClient);

现在你可以:

var client = MongoClient.connectAsync('mongodb://localhost:27017/test')
    .then(function(db) {
        return db.collection("myCollection").findOneAsync({ id: 'someId' })
    })
    .then(function(item) {
      // Use `item`
    })
    .catch(function(err) {
        // An error occurred
    });

这会让你走得很远,除了它还有助于确保Cursor返回的Collection#find()个对象也是有效的。在MongoDB JS驱动程序中,Collection#find()返回的游标不是从原型构建的。因此,您可以包装方法并每次都传播游标。如果您不使用游标,或者不想承担开销,则这不是必需的。这是一种方法:

Collection.prototype._find = Collection.prototype.find;
Collection.prototype.find = function() {
    var cursor = this._find.apply(this, arguments);
    cursor.toArrayAsync = Promise.promisify(cursor.toArray, cursor);
    cursor.countAsync = Promise.promisify(cursor.count, cursor);
    return cursor;
}

答案 2 :(得分:10)

I know this has been answered several times, but I wanted to add in a little more information regarding this topic. Per Bluebird's own documentation, you should use the 'using' for cleaning up connections and prevent memory leaks. Resource Management in Bluebird

I looked all over the place for how to do this correctly and information was scarce so I thought I'd share what I found after much trial and error. The data I used below (restaurants) came from the MongoDB sample data. You can get that here: MongoDB Import Data

// Using dotenv for environment / connection information
require('dotenv').load();
var Promise = require('bluebird'),
    mongodb = Promise.promisifyAll(require('mongodb'))
    using = Promise.using;

function getConnectionAsync(){
    // process.env.MongoDbUrl stored in my .env file using the require above
    return mongodb.MongoClient.connectAsync(process.env.MongoDbUrl)
        // .disposer is what handles cleaning up the connection
        .disposer(function(connection){
            connection.close();
        });
}

// The two methods below retrieve the same data and output the same data
// but the difference is the first one does as much as it can asynchronously
// while the 2nd one uses the blocking versions of each
// NOTE: using limitAsync seems to go away to never-never land and never come back!

// Everything is done asynchronously here with promises
using(
    getConnectionAsync(),
    function(connection) {
        // Because we used promisifyAll(), most (if not all) of the
        // methods in what was promisified now have an Async sibling
        // collection : collectionAsync
        // find : findAsync
        // etc.
        return connection.collectionAsync('restaurants')
            .then(function(collection){
                return collection.findAsync()
            })
            .then(function(data){
                return data.limit(10).toArrayAsync();
            });
    }
// Before this ".then" is called, the using statement will now call the
// .dispose() that was set up in the getConnectionAsync method
).then(
    function(data){
        console.log("end data", data);
    }
);

// Here, only the connection is asynchronous - the rest are blocking processes
using(
    getConnectionAsync(),
    function(connection) {
        // Here because I'm not using any of the Async functions, these should
        // all be blocking requests unlike the promisified versions above
        return connection.collection('restaurants').find().limit(10).toArray();
    }
).then(
    function(data){
        console.log("end data", data);
    }
);

I hope this helps someone else out who wanted to do things by the Bluebird book.

答案 3 :(得分:7)

mongodb版本1.4.9现在应该很容易实现:

Promise.promisifyAll(mongo.Cursor.prototype);

有关详细信息,请参阅https://github.com/mongodb/node-mongodb-native/pull/1201

答案 4 :(得分:0)

我们一直在生产中使用以下驱动程序。它本质上是本机node.js驱动程序的承诺包装器。它还增加了一些辅助函数。

poseidon-mongo - https://github.com/playlyfe/poseidon-mongo