【发布时间】:2014-02-21 15:21:57
【问题描述】:
我有一个函数createOne(),它应该尝试查找一个 MongoDB 文档,如果找不到则创建它。无论哪种方式,都应该返回一个 Promise,并使用 doc 解决该 Promise:
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()(应该)都返回一个承诺。
我尝试了许多不同的方法,例如使用 Q.fcall、使用 Q.defer() 和其他方法手动创建一个,但要么缺少解析值,要么即使第一个也创建了第二个 { 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) 返回文档,无论它们是先找到还是先创建?
编辑:当集合为空时,应该只创建两个文档。 { slug: 'foo' } 只有一次。
【问题讨论】:
-
不应该
if (!doc)有一个else子句直接返回doc吗? -
a) 这只是伪代码还是您的
.exec()调用已经返回了一个承诺(使用.then()方法)? b) mongoose 如何发出未找到文档的信号,是错误还是通过null? -
是的,没错,谢谢!返回值现在可以了 :) 我认为第二个
{ slug: 'foo' }是创建的,因为我调用了我的createOne()快速射击样式,而不是等待异步查找/创建调用完成。会这样吗? -
@Bergi
exec()确实返回了一个承诺。如果没有找到文档,doc是null。 -
@JohnB.:你的意思是一个竞争条件,两个查询都表示没有可用的文档,然后都创建一个?是的,如果没有交易管理系统,这很容易发生。如果
promises不并行执行会好吗?
标签: javascript node.js asynchronous promise q