web-dev-qa-db-ja.com

Bluebirdを使用してMongoDBネイティブJavascriptドライバーを約束する方法を教えてください。

MongoDBネイティブJSドライバーbluebird promises を併用したいと思います。このライブラリで Promise.promisifyAll() を使用するにはどうすればよいですか?

24

2.0ブランチのドキュメントには、より適切なガイドが含まれています https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification

実際には、もっと単純なmongodbの例があります。

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

Promise.promisifyAll()を使用する場合、ターゲットオブジェクトをインスタンス化する必要がある場合、ターゲットプロトタイプを識別するのに役立ちます。 MongoDB JSドライバーの場合、標準パターンは次のとおりです。

  • Db静的メソッドまたはMongoClientコンストラクターを使用して、Dbオブジェクトを取得します
  • Db#collection()を呼び出して、Collectionオブジェクトを取得します。

したがって、 https://stackoverflow.com/a/21733446/74197 から借用すると、次のことができます。

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

Collection#find()によって返されるCursorオブジェクトも約束されていることを確認するのに役立つことを除いて、これはかなり遠くまで届きます。 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;
}
_
18

私はこれが何度か回答されたことを知っていますが、このトピックに関するもう少し情報を追加したいと思いました。 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);
    }
);

これがブルーバードの本で何かをしたいと思っていた誰かを助けることを願っています。

10
Allen Underwood

mongodbのバージョン1.4.9は、次のように簡単に利用できるはずです。

Promise.promisifyAll(mongo.Cursor.prototype);

詳細は https://github.com/mongodb/node-mongodb-native/pull/1201 を参照してください。

7
knpwrs

しばらくの間、次のドライバーを本番環境で使用しています。基本的には、ネイティブのnode.jsドライバーに対するpromiseラッパーです。また、いくつかのヘルパー関数が追加されています。

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

0
Rajan