承诺返回值和嵌套

我有一个函数createOne()应该试图find一个MongoDB文档或创build它,如果找不到。 无论哪种方式,都应该返回一个承诺,并用doc解决承诺:

 var createOne = function(category) { var self = this; return this.findOne({ slug: category.slug }).exec() .then(function(doc) { if (!doc) { return self.create(category); // wait to resolve until document created. } }); }; 

findOne().exec()create() (应该)都返回一个promise。

我尝试了很多不同的方法,比如使用Q.fcall,用Q.defer()和其他方法手动创build一个,但是parsing值丢失,或者创build了第二个{ slug: 'foo' } ,即使首先已经存在(?)。

以下是我的通话代码:

 var data = [ { slug: 'foo' }, { slug: 'bar' }, { slug: 'foo' } // <- shouldn't be created because of first 'foo'. ]; Q.fcall(function() { // [...] }).then(function() { var promises = data.map(function(category) { return createOne(category); // <- calls createOne(). }); return Q.all(promises); }).then(function(categories) { console.log(categories); }).done(); 

我如何构造createOne()以便console.log(categories)返回文档,无论它们是首先find还是创build?

编辑:当集合为空时,只能创build两个文档。 { slug: 'foo' }只有一次。

看来我已经想出了如何顺序调用asynchronous函数,并组成了所有promise的最终数组(以及后来的parsing值)。

我的解决scheme基于一个很棒的array.reduce示例,我在Github的kriskowal的评论中find了这个示例。

 var data = [ 'Element 1', 'Element 2', 'Element 3' ]; function asyncMock(element) { console.log('Handle', element); return Q.delay(element + ' handled.', 500); } var promise = data.reduce(function (results, element) { return results.then(function (results) { return asyncMock(element).then(function(result) { results.push(result); return results; }); }); }, Q([])); promise.then(function(elements) { console.log('Finished:', elements); }).done(); 

你可以在这里find一个工作演示: http : //jsfiddle.net/Lnvu4/