Mongodb节点驱动2.0。*与Bluebird 2.9。* promisification

所以围绕这个主题还有一些其他的疑问,比如: 我怎样才能使用蓝鸟提供MongoDB本地的Javascript驱动?

然而,它似乎并没有解决最新版本的驱动程序,这似乎有问题,当试图promisify时。 目前我可以通过执行MongoClient工作:

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

然而,无论我尝试着什么,Collections似乎都不会使用*async调用操作,它可能会调用它们,但是它们永远不会被解决或被拒绝,所以它们只能被挂起。

历史上在以前的版本,你只会Promise.promisifyAll(mongodb) ,你已经完成了,但我不确定如何正确处理这个新的驱动程序。

下面是一个使用mongo direct promisification connectAsync创build的集合的示例输出,然后从返回的数据库获取集合。 一旦我尝试在集合上做任何事情,它只是挂起,承诺不会从它回来:

{ 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' } }

您可以在要求之后直接提供,如蓝鸟API文档中所示 ,例如:

 var Promise = require("bluebird"); var MongoDB = Promise.promisifyAll(require("mongodb")); var util = require('util'); console.log(util.inspect(MongoDB, { showHidden: true })); 

使用蓝鸟2.9.14和mongodb驱动2.0.22,我得到了这个(简化)的结果:

  // .... 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], // .... 

并成功地这样查询:

 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

使用MongoClient对象也是如此:

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

默认情况下,如果不指定callback,mongodb驱动程序总是返回一个promise。 但是您可以指示它使用您的首选承诺库返回承诺。

在使用node-mongodb-native 2.0驱动程序时,以下是使用蓝鸟许诺的简单方法:

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

简化和更现实的版本:

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

承诺嵌套完成是为了将数据库暴露给逻辑的其余部分。 通过全局传递或者声明'db'也可以不嵌套。 试了一下,这一个是最优雅的。

您可以阅读MongoDB本地驱动程序的源代码:

 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可以设置为蓝鸟