Bluebird promisesでMongoDB ネイティブ JS ドライバーを使用したいと思います。このライブラリでどのように使用できますか?Promise.promisifyAll()
5 に答える
2.0 ブランチのドキュメントには、より良い約束ガイドが含まれています https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification
実際には、はるかに単純な mongodb の例があります。
var Promise = require("bluebird");
var MongoDB = require("mongodb");
Promise.promisifyAll(MongoDB);
を使用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()
プロトタイプから構築されていません。したがって、メソッドをラップして、毎回カーソルを約束することができます。カーソルを使用しない場合、またはオーバーヘッドを発生させたくない場合、これは必要ありません。1 つのアプローチを次に示します。
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;
}
これは何度か回答されていることは知っていますが、このトピックに関する情報をもう少し追加したいと思いました. Bluebird 自身のドキュメントによると、「using」を使用して接続をクリーンアップし、メモリ リークを防ぐ必要があります。 Bluebird でのリソース管理
これを正しく行う方法をあちこち探しましたが、情報が不足していたので、多くの試行錯誤の末に見つけたものを共有すると思いました. 以下で使用したデータ (レストラン) は、MongoDB サンプル データから取得したものです。ここで取得できます: 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);
}
);
これが、ブルーバードの本で何かをしたいと思っている誰かの助けになることを願っています.
のバージョン 1.4.9 は、次のmongodb
ように簡単に約束できるはずです。
Promise.promisifyAll(mongo.Cursor.prototype);
詳細については、 https://github.com/mongodb/node-mongodb-native/pull/1201を参照してください。