Promise和nodejs MongoDB驱动程序

我想向MongoDB驱动程序作出承诺。 我写了下面的代码:

var TaskBroker = function () { this.queueName = 'task_queue'; this.rabbit = {}; this.mongo = {}; }; TaskBroker.prototype.connectRabbit = function() { var self = this; return amqp.connect('amqp://localhost') .then(function(connection) { self.rabbit.connection = connection; return connection.createChannel() }) .then(function(channel) { self.rabbit.channel = channel; return channel.assertQueue(self.queueName, {durable: true}); }) }; TaskBroker.prototype.connectMongo = function() { console.log('Connect Mongo'); var self = this; var defer = q.defer(); MongoClient.connect('mongodb://127.0.0.1:27017/test', {}, defer.makeNodeResolver()); return defer.promise.then(function(db) { self.mongo.db = db; console.log('hello'); return 42; }); }; TaskBroker.prototype.connect = function () { var self = this; return this.connectRabbit() .then(self.connectMongo); }; 

你有什么想法,当我调用方法connect时,为什么我没有输出hello

 taskBroker.connect() .then(function(result) { console.log('Disconnected'); taskBroker.disconnect(); }); 

手动promisifying一个API是危险的,我提出了一些沿线:

 TaskBroker.prototype._connectMongo = Q.nfcall(MongoClient.connect, 'mongodb://127.0.0.1:27017/test', {}); TaskBroker.prototype.connectMongo = function(){ return this._connectMongo().then(function(db){ console.log("Hello"); // self.stuff... return 42; }).catch(function(e){ console.err("connection error",e); // log the connection error, or handler err throw e; // don't mark as handled, propagate the error. }); }; 

蓝鸟承诺,看起来像这样:

 var MongoClient = Promise.promisifyAll(require("mongodb").MongoClient); TaskBroker.prototype.connectMongo = function(){ return MongoClient.connectAsync().then(... // Bluebird will automatically track unhandled errors }; 

MongoDB的

为了处理mongodb驱动,我build议使用mongo (免责声明:我写的)。 除了使用promises而不是callback之外,这相当于mongojs 。 它还允许您将“连接”操作视为同步操作,方法是立即返回可与之交互的对象,并仅等待内部连接。 真正好的是它与官方的mongodb文档相匹配,所以你可以使用该文档来弄清楚如何使用它。

一般情况

通常,使用Promise构造函数来获取不返回promise的API。 例如

 function readFile(filename, enc){ return new Promise(function (fulfill, reject){ fs.readFile(filename, enc, function (err, res){ if (err) reject(err); else fulfill(res); }); }); } 

如果你使用Q你应该这样做:

 function readFile(filename, enc){ return q.promise(function (fulfill, reject){ fs.readFile(filename, enc, function (err, res){ if (err) reject(err); else fulfill(res); }); }); } 

帮手方法

包括许多库,提供了特殊的辅助方法来调整node.js风格的callback方法来返回promise。 例如

 var readFile = q.denodeify(fs.readFile); 

或承诺 :

 var readFile = Promise.denodeify(fs.readFile); 

如果你想了解更多关于如何创build和使用Promise对象的信息(而不是特定的Q),我build议你查看一下https://www.promisejs.org/(diclaimer :我写的)。

节点mongodb驱动程序v2.0.36引入了对promise的一stream支持。

以下是官方文档的一个示例:

 // A simple query showing skip and limit using a Promise. var MongoClient = require('mongodb').MongoClient, test = require('assert'); MongoClient.connect('mongodb://localhost:27017/test', function(err, db) { // Create a collection we want to drop later var collection = db.collection('simple_limit_skip_query_with_promise'); // Insert a bunch of documents for the testing collection.insertMany([{a:1, b:1}, {a:2, b:2}, {a:3, b:3}], {w:1}).then(function(result) { // Peform a simple find and return all the documents collection.find({}) .skip(1).limit(1).project({b:1}).toArray().then(function(docs) { test.equal(1, docs.length); test.equal(null, docs[0].a); test.equal(2, docs[0].b); db.close(); }); }); }); 

默认情况下,使用es6-promise库,但是在创build数据库连接时可以覆盖它:

 var MongoClient = require('mongodb').MongoClient; MongoClient.connect('mongodb://localhost:27017/test', { promiseLibrary: require('bluebird') }, function(err, db) { // ...