nodejs - ¿Cómo puedo promisificar el controlador de JavaScript nativo de MongoDB con bluebird?
mongoose (5)
Al usar Promise.promisifyAll()
, ayuda a identificar un prototipo de destino si su objeto de destino debe ser instanciado. En el caso del controlador MongoDB JS, el patrón estándar es:
- Obtiene un objeto
Db
, utilizando el método estáticoMongoClient
o el constructorDb
- Call
Db#collection()
para obtener un objetoCollection
.
Entonces, tomando prestado de https://stackoverflow.com/a/21733446/741970 , puede:
var Promise = require(''bluebird'');
var mongodb = require(''mongodb'');
var MongoClient = mongodb.MongoClient;
var Collection = mongodb.Collection;
Promise.promisifyAll(Collection.prototype);
Promise.promisifyAll(MongoClient);
Ahora usted puede:
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
});
Esto lo lleva bastante lejos, excepto que también ayudará a asegurarse de que los objetos del Cursor
devueltos por Collection#find()
también sean promisificados. En el controlador MongoDB JS, el cursor devuelto por Collection#find()
no se genera a partir de un prototipo. Por lo tanto, puede ajustar el método y promisificar el cursor cada vez. Esto no es necesario si no utiliza los cursores o no desea incurrir en gastos generales. Aquí hay un enfoque:
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;
}
Me gustaría usar el controlador JS nativo de MongoDB con las promesas de bluebird . ¿Cómo puedo usar Promise.promisifyAll()
en esta biblioteca?
Hemos estado utilizando el siguiente controlador en producción desde hace un tiempo. Es esencialmente un envoltorio de promesa sobre el controlador node.js nativo. También agrega algunas funciones auxiliares adicionales.
poseidon-mongo
- https://github.com/playlyfe/poseidon-mongo
La documentación de la sucursal 2.0 contiene una mejor guía de promisión https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification
De hecho, tiene un ejemplo de mongodb que es mucho más simple:
var Promise = require("bluebird");
var MongoDB = require("mongodb");
Promise.promisifyAll(MongoDB);
La versión 1.4.9 de mongodb
ahora debería ser fácilmente promisable como tal:
Promise.promisifyAll(mongo.Cursor.prototype);
Consulte https://github.com/mongodb/node-mongodb-native/pull/1201 para obtener más detalles.
Sé que esto ha sido respondido varias veces, pero quería agregar un poco más de información sobre este tema. Según la propia documentación de Bluebird, debe usar ''usar'' para limpiar conexiones y evitar fugas de memoria. Gestión de recursos en Bluebird
Miré por todas partes para saber cómo hacer esto correctamente y la información era escasa, así que pensé en compartir lo que encontré después de mucho ensayo y error. Los datos que utilicé a continuación (restaurantes) provienen de los datos de muestra de MongoDB. Puede obtenerlo aquí: 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);
}
);
Espero que esto ayude a alguien más que quería hacer cosas con el libro de Bluebird.