wake-up-neo.com

Wie kann ich den in MongoDB eingebauten Javascript-Treiber mit Bluebird versprechen?

Ich möchte den MongoDB-nativen JS-Treiber mit bluebird Versprechen verwenden. Wie kann ich Promise.promisifyAll() für diese Bibliothek verwenden?

24

Die 2.0-Zweigdokumentation enthält einen besseren Versprechungsleitfaden https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification

Es hat tatsächlich ein Mongodb-Beispiel, das viel einfacher ist:

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

Bei Verwendung von Promise.promisifyAll() kann ein Zielprototyp identifiziert werden, wenn das Zielobjekt instanziiert werden muss. Im Falle des MongoDB JS-Treibers lautet das Standardmuster:

  • Rufen Sie ein Db-Objekt ab, verwenden Sie entweder die MongoClient statische Methode oder den Db-Konstruktor
  • Rufen Sie Db#collection() auf, um ein Collection-Objekt abzurufen.

Wenn Sie von https://stackoverflow.com/a/21733446/741970 leihen, können Sie:

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

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

Jetzt kannst du:

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

Dies bringt Sie ziemlich weit, außer es hilft auch sicherzustellen, dass die von Collection#find() zurückgegebenen Cursor-Objekte ebenfalls versprochen werden. Im MongoDB-JS-Treiber wird der von Collection#find() zurückgegebene Cursor nicht aus einem Prototyp erstellt. Sie können also die Methode umschließen und den Cursor jedes Mal versprechen. Dies ist nicht erforderlich, wenn Sie keine Cursor verwenden oder den Overhead nicht übernehmen möchten. Hier ist ein Ansatz:

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;
}
18

Ich weiß, dass dies mehrmals beantwortet wurde, aber ich wollte ein wenig mehr Informationen zu diesem Thema hinzufügen. Laut Bluebirds eigener Dokumentation sollten Sie das 'using' verwenden, um Verbindungen zu bereinigen und Speicherlecks zu vermeiden. Ressourcenverwaltung in Bluebird

Ich habe mich überall umgesehen, um herauszufinden, wie man das richtig macht, und es gab nur wenige Informationen. Deshalb dachte ich, ich würde das, was ich nach langem Ausprobieren gefunden habe, mit anderen teilen. Die Daten, die ich unten verwendet habe (Restaurants), stammen aus den MongoDB-Beispieldaten. Das können Sie hier bekommen: 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);
    }
);

Ich hoffe, das hilft jemand anderem, der Dinge nach dem Bluebird-Buch machen wollte.

10
Allen Underwood

Die Version 1.4.9 von mongodb sollte nun als solche einfach zu versprechen sein:

Promise.promisifyAll(mongo.Cursor.prototype);

Unter https://github.com/mongodb/node-mongodb-native/pull/1201 finden Sie weitere Einzelheiten.

7
knpwrs

Wir haben den folgenden Treiber schon länger in der Produktion eingesetzt. Es ist im Wesentlichen ein Versprechen-Wrapper über den nativen node.js-Treiber. Es fügt auch einige zusätzliche Hilfsfunktionen hinzu.

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

0
Rajan