我想用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);
};
当我调用方法hello
时,您是否知道我为什么没有输出connect
:
taskBroker.connect()
.then(function(result) {
console.log('Disconnected');
taskBroker.disconnect();
});
答案 0 :(得分:9)
手动宣传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.
});
};
有了Bluebird的承诺,它看起来像是:
var MongoClient = Promise.promisifyAll(require("mongodb").MongoClient);
TaskBroker.prototype.connectMongo = function(){
return MongoClient.connectAsync().then(...
// Bluebird will automatically track unhandled errors
};
答案 1 :(得分:7)
v2.0.36引入了对promises的一流支持。
以下是官方文档中的一个示例:
// 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库,但您可以在创建数据库连接时覆盖它:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/test', {
promiseLibrary: require('bluebird')
}, function(err, db) {
// ...
答案 2 :(得分:6)
为了处理mongodb驱动程序,我建议使用then-mongo(免责声明:我写了它)。这相当于mongojs,除了使用promises而不是回调。它还允许您通过立即返回可以与之交互的对象并仅在内部等待连接来将“连接”操作视为同步操作。非常好的是它与官方的mongodb文档相匹配,因此您可以使用该文档来弄清楚如何使用它。
一般情况下,使用Promise构造函数来获取不返回promise并获取promise的API。 e.g。
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);
});
});
}
包含Q的许多库提供了特殊的帮助器方法,用于调整node.js样式的回调方法以返回promise。 e.g。
var readFile = q.denodeify(fs.readFile);
或promise:
var readFile = Promise.denodeify(fs.readFile);
如果您想了解更多关于如何创建和使用Promise对象的信息(而不是Q特定的),我建议您查看https://www.promisejs.org/(免责声明:我写了它)。