Node.js承诺与mongoskin

我试图避免在进行mongodb查询时使用callback。 我使用mongoskin来打电话,如下所示:

req.db.collection('users').find().toArray(function (err, doc) { res.json(doc); }); 

在许多情况下,我需要做多个查询,所以我想使用Node.js承诺库,但我不知道如何将这些函数作为承诺包装。 我看到的大多数例子对于像readFile这样的事情来说都是微不足道的,我猜在这种情况下,我需要以某种方式包装到Array中。 这可以做,或将不得不由蒙古人实施的东西?

一个例子可以是任何一组callback,find / insert,find / find / insert,find / update:

 req.db.collection('users').find().toArray(function (err, doc) { if (doc) { req.db.collection('users').find().toArray(function (err, doc) { // etc... }); } else { // err } }); 

你可以像蓝鸟一样用promisify整个模块:

 var Promise = require("bluebird"); var mongoskin = require("mongoskin"); Object.keys(mongoskin).forEach(function(key) { var value = mongoskin[key]; if (typeof value === "function") { Promise.promisifyAll(value); Promise.promisifyAll(value.prototype); } }); Promise.promisifyAll(mongoskin); 

这只需要在应用程序中的一个地方执行一次,而不是在应用程序代码中的任何地方执行。

之后,除了Async后缀以外,通常只使用方法,不要传递callback:

 req.db.collection('users').find().toArrayAsync() .then(function(doc) { if (doc) { return req.db.collection('users').find().toArrayAsync(); } }) .then(function(doc) { if (doc) { return req.db.collection('users').find().toArrayAsync(); } }) .then(function(doc) { if (doc) { return req.db.collection('users').find().toArrayAsync(); } }); 

所以再次,如果你调用一个函数

 foo(a, b, c, function(err, result) { if (err) return console.log(err); //Code }); 

承诺返回版本被称为:

 fooAsync(a, b, c).then(...) 

(未捕获的错误会自动logging,所以如果你只是要logging它,你不需要检查它们)

刚刚在这里遇到了同样的问题,不喜欢“promingfying”mongoskin所以做了一点挖掘,find了和尚 。 它build立在mongoskin之上,整理API并返回所有asynchronous调用的承诺。 也许值得一窥在这里登陆的任何人。

Esailija的答案可能会起作用,但它不是非常高效,因为你必须在每个db调用中运行db.collection。 我不知道究竟是多么昂贵,但是在mongoskin中查看代码是非常重要的。 不仅如此,而且它在全球范围内修改原型,这不是很安全。

我用纤维期货做这件事的方式是:

  1. 包装每个集合的收集方法
  2. 在接收到结果的时候,对于返回一个Cursor的方法包装了toArray方法,调用它并返回结果的未来(对于不返回游标的方法,你不需要做任何事情)。
  3. 正常使用未来

喜欢这个:

 var Future = require("fibers/future") // note: when i originally wrote this answer fibers/futures didn't have a good/intuitive wrapping function; but as of 2014-08-18, it does have one function futureWrap() { // function if(arguments.length === 1) { var fn = arguments[0] var object = undefined // object, methodName } else { var object = arguments[0] var fn = object[arguments[1]] } return function() { var args = Array.prototype.slice.call(arguments) var future = new Future args.push(future.resolver()) var me = this if(object) me = object fn.apply(me, args) return future } } var methodsYouWantToHave = ['findOne', 'find', 'update', 'insert', 'remove', 'findAndModify'] var methods = {} methodsYouWantToHave.forEach(function(method) { internalMethods[method] = futureWrap(this.collection, method) }.bind(this)) // use them var document = methods.findOne({_id: 'a3jf938fj98j'}, {}).wait() var documents = futureWrap(methods.find({x: 'whatever'}, {}).wait(), 'toArray')().wait() 

如果你不想使用光纤,我build议使用async-future模块 ,它也有很好的包装function。