【问题标题】:Promise return value and nestingPromise 返回值和嵌套
【发布时间】: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() 确实返回了一个承诺。如果没有找到文档,docnull
  • @JohnB.:你的意思是一个竞争条件,两个查询都表示没有可用的文档,然后都创建一个?是的,如果没有交易管理系统,这很容易发生。如果promises不并行执行会好吗?

标签: javascript node.js asynchronous promise q


【解决方案1】:

看来我已经弄清楚如何顺序调用异步函数并组成一个包含所有承诺(以及后来解析的值)的最终数组。

我的解决方案基于我在 Github 上的 comment from kriskowal 中找到的一个很好的 array.reduce 示例。

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();

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

【讨论】:

    猜你喜欢
    • 2020-04-13
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    相关资源
    最近更新 更多