2015-03-18 10 views
9

więc istnieje kilka innych zapytań wokół tej kwestii, takich jak: How can I promisify the MongoDB native Javascript driver using bluebird?węzeł MongoDB kierowca 2,0 * z Bluebird 2,9 * promisification

Jednak nie wydaje się, aby rozwiązać najnowszą wersję sterownika, który wydaje mieć problemy podczas próby promisify. Obecnie można uzyskać MongoClient pracuje wykonując:

Promise.promisifyAll(mongodb.MongoClient); // Using .Prototype here fails to promisify

Jednak bez względu na to, co staram się Collections nie wydają się działać przy użyciu połączenia *async, może je wywołać, ale nigdy nie zostanie rozwiązany lub odrzucone więc po prostu zwisają w otchłani.

Historycznie w poprzednich wersjach byłeś po prostu Promise.promisifyAll(mongodb) i skończyłeś, ale nie jestem pewien, jak poprawnie obsłużyć to w nowym sterowniku.

Oto przykładowe dane wyjściowe kolekcji, która została utworzona za pomocą mongo direct promisification connectAsync, a następnie pobranie kolekcji z zwróconej bazy danych. Raz spróbować zrobić coś w sprawie zbierania po prostu zawiesza się i obiecuje dont powrócić z nim:

{ s: { pkFactory: { [Function: ObjectID] index: 14727641, createPk: [Function: createPk], createFromTime: [Function: createFromTime], createFromHexString: [Function: createFromHexString], isValid: [Function: isValid], ObjectID: [Circular], ObjectId: [Circular], createPkAsync: [Object], createFromTimeAsync: [Object], createFromHexStringAsync: [Object], isValidAsync: [Object], bindAsync: [Object], toStringAsync: [Object], callAsync: [Object], applyAsync: [Object], lazyAsync: [Object], throttleAsync: [Object], debounceAsync: [Object], delayAsync: [Object], everyAsync: [Object], cancelAsync: [Object], afterAsync: [Object], onceAsync: [Object], fillAsync: [Object] }, db: { domain: [Object], _events: {}, _maxListeners: undefined, s: [Object], serverConfig: [Getter], bufferMaxEntries: [Getter], databaseName: [Getter], options: [Getter], native_parser: [Getter], slaveOk: [Getter], writeConcern: [Getter] }, topology: { domain: [Object], _events: [Object], _maxListeners: undefined, connectTimeoutMS: 500, s: [Object], bson: [Getter], isMasterDoc: [Getter], poolSize: [Getter], autoReconnect: [Getter], host: [Getter], port: [Getter], emitOpen: false, socketTimeoutMS: 0 }, dbName: 'some-db-name', options: {}, namespace: 'some-namespace', readPreference: null, raw: undefined, slaveOk: false, serializeFunctions: undefined, internalHint: null, collectionHint: null, name: 'some-collection-name' } }

+0

Dla każdego, kto na to patrzy, w Mong o 2. * Wydaje się, że zmieniają one to, co jest zwracane z pewnych metod, jak np. findAsync wydaje się teraz zwracać kilka dużych modeli zamiast dokumentów, które otrzymywałem wcześniej, więc ten problem jest w połowie drogi między koniecznością migracji logiki i konieczności dobrze ją uzasadnić. – Grofit

Odpowiedz

8

Można promisify go bezpośrednio po wymagających, jak zilustrowano na bluebird API docs, tak:

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

console.log(util.inspect(MongoDB, { showHidden: true })); 

Korzystanie Bluebird 02.09.14 i MongoDB sterownik 2.0.22, mam to (uproszczony) wyniki:

// .... 
    Collection: 
    { [Function] 
    [length]: 6, 
    [name]: '', 
    [arguments]: [Getter/Setter], 
    [caller]: [Getter/Setter], 
    [prototype]: 
     { [constructor]: [Circular], 
     collectionName: [Getter], 
     // .... 
     findAsync: [Object], 
     insertOneAsync: [Object], 
     insertManyAsync: [Object], 
     bulkWriteAsync: [Object], 
     insertAsync: [Object], 
     updateOneAsync: [Object], 
     replaceOneAsync: [Object], 
     updateManyAsync: [Object], 
     updateAsync: [Object], 
     deleteOneAsync: [Object], 
     removeOneAsync: [Object], 
     deleteManyAsync: [Object], 
     removeManyAsync: [Object], 
     removeAsync: [Object], 
     saveAsync: [Object], 
     findOneAsync: [Object], 
     // .... 

i zapytaliśmy successfu lly tak:

MongoDB.connectAsync('mongodb://localhost:27017/test').then(function(db) { 
    return db.collection("orders").findOneAsync({}); 
}).then(function(orders) { 
    console.log(orders); 
}).catch(function(err) { 
    console.log(err); 
}); 

UPDATE

Używanie obiektu MongoClient działa tak samo:

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

MongoClient.connectAsync('mongodb://localhost:27017/test').then(function(db) { 
    return db.collection("orders").find({}).toArrayAsync(); 
}).then(function(orders) { 
    console.log(orders) 
}).catch(function(err) { 
    console.log(err); 
}); 
+0

Wykonuję powyższe czynności i widzę, że niektóre metody mają metody asynchroniczne, ale obiekt 'MongoClient' zawiera tylko' connect', a nie 'connectAsync'. Jednak w twoim przykładzie sugerujesz, że łączysz się bezpośrednio z obiektem mongodb nie na obiekcie 'mongodb.MongoClient', który jest wymieniony w dokumentacji: http://mongodb.github.io/node-mongodb-native/2.0/ ponownie uruchamiasz swój kod i wypisujesz obiekt 'MongoClient', który może rzucić trochę światła na tę sprawę, ponieważ reszta może być związana, ale' connectAsync' po prostu nie istnieje na powyższym przykładzie. (z MongoClient) – Grofit

+0

Mogę potwierdzić, że powyższe połączenie przez podstawowy obiekt mongodb działa w ten sposób, ale pozostałe obiekty nadal nie zachowują się zgodnie z oczekiwaniami. Na przykład łączę się teraz, korzystając ze sposobu przedstawionego powyżej, a następnie tworząc kolekcję, której obiekt nie wygląda tak jak twój. Opublikuję edycję z danymi wyjściowymi moich obiektów kolekcji. – Grofit

+0

Zaktualizowałem swoją odpowiedź na przykładzie za pomocą obiektu 'MongoClient'. Opublikowane przeze mnie dane wyjściowe pochodziły z podstawowego obiektu 'MongoDB', a nie z' db.collection() '. Mimo to, mógłbym zapytać bazę danych jak zwykle za pomocą funkcji * Async. – victorkohl

1

Usprawnione i bardziej realistyczna wersja:

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

MongoDB.MongoClient.connectAsync('mongodb://localhost:27017/test') 
    .then(function(db) { // Expose db to query logic 
    // need to return a promise to let outer catch handle it 
    return db.collection("orders").find({}).toArrayAsync() 
     .then(function (orders) { 
     console.log(orders); 
     }) 
     // Ensure that db is closed at the end no matter what... 
     .finally(db.close.bind(db)); 
     // No need for another catch here, the outer one will handle it 
    }) 
    .catch(console.log.bind(console)); 

Obietnica gniazdowania odbywa w celu ujawnienia db do Reszta logiki. To samo można zrobić bez zagnieżdżania przez przekazanie lub deklarowanie "db" globalnie. Wypróbowałem to wszystko i ten jest najbardziej elegancki.

8

Domyślnie sterownik mongodb zawsze zwraca obietnicę, jeśli nie określisz wywołania zwrotnego. Ale możesz polecić, by zwrócił obietnice, korzystając z biblioteki preferowanych obietnic.

Oto prosty sposób korzystać Bluebird obietnic podczas korzystania node-mongodb-native 2.0 sterownik:

var Promise = require("bluebird"); 
var MongoClient = require("mongodb").MongoClient; // Doesn't require promisification 

/*...*/ 
function saveData(data) { 
    MongoClient 
    .connect(MONGO_CONNECTION_STRING, { 
     promiseLibrary: Promise // Here you instruct to use bluebird 
    }) 
    .then(function(db) { 
     return db 
     .collection('myCollection') 
     .insert(data) 
     .finally(db.close.bind(db)) 
    }) 
    .catch(function(err) { 
     console.error("ERROR", err); 
    }); 
} 
+0

Należy również pamiętać o tej notatce: http://bluebirdjs.com/docs/api/resource-management.html – Tom

+0

Jeśli używasz find, musisz ustawić kursor przed zamknięciem bazy danych, ale wydaje się, że najlepsze rozwiązanie. – conradj

+0

Tak, musisz go skonsumować przed zamknięciem. W rzeczywistości wolelibyśmy pozostawić otwarte połączenia, ponieważ każde zapytanie jest dość kosztowne. Po prostu próbowałem stworzyć rodzaj "pełnego cyklu", ale zdecydowanie zalecam ponowne użycie twoich połączeń. Sterownik Mongo może zarządzać pulą połączeń niemal bez przeszkód. –

0

można odczytać źródło MongoDB Native Kierowca:

MongoClient.connect = function(url, options, callback) { 
    var args = Array.prototype.slice.call(arguments, 1); 
    callback = typeof args[args.length - 1] == 'function' ? args.pop() : null; 
    options = args.length ? args.shift() : null; 
    options = options || {}; 

    // Get the promiseLibrary 
    var promiseLibrary = options.promiseLibrary; 

    // No promise library selected fall back 
    if(!promiseLibrary) { 
    promiseLibrary = typeof global.Promise == 'function' ? 
     global.Promise : require('es6-promise').Promise; 
    } 

    // Return a promise 
    if(typeof callback != 'function') { 
    return new promiseLibrary(function(resolve, reject) { 
     connect(url, options, function(err, db) { 
     if(err) return reject(err); 
     resolve(db); 
     }); 
    }); 
    } 

    // Fallback to callback based connect 
    connect(url, options, callback); 
} 

promiseLibrary można setted Bluebird

Powiązane problemy