【问题标题】:Is there a simpler way to chain promises from MongoDB results? [duplicate]有没有更简单的方法来链接来自 MongoDB 结果的承诺? [复制]
【发布时间】:2016-10-05 22:22:27
【问题描述】:

此函数列出 MongoDB 数据库中的所有集合,以及每个集合中的文档数 (bluebird promises)。

function listMongoCollections(db) {
    var promises = []
    db.listCollections().toArray().then((docs) => {

        docs.forEach((doc) => {

            promises.push(
                new Promise((resolve) => {
                    db.collection(doc.name).count().then((count) => {
                        doc.count = count
                        resolve()
                    })
                })
            )
        })

        return Promise.all(promises)
    })
}

有没有更简单的方法来做到这一点?使用这种方法会使应用程序充满代码,我什至没有包括错误处理。

【问题讨论】:

  • 你可以试试 Q. 在 JavaScript 中创建和编写异步 promise 的工具documentup.com/kriskowal/q
  • 我没有看到 Q 做任何蓝鸟不能做的事情
  • @PålThingbø 作为 Q 和 Bluebird 的贡献者 - 我可以确认这一说法。

标签: javascript node.js mongodb promise


【解决方案1】:

你可以做一些事情:

  • 使用.map 将集合数组转换为promise 数组,而不是手动将.push 转换为数组。
  • 避免在新的 Promise 中包装 Promise。
  • 尽可能少地嵌套.then。在下面的示例中,请注意第一部分如何仅返回一个 promise 数组。仅在返回 main 函数之前,我们将其包装在 .all 承诺中。
function listMongoCollections(db) {
    const docs = db.listCollections().toArray().then(docs => {
        return docs.map(doc => {
            return db.collection(doc.name).count().then(count => {
                doc.count = count
                return doc;
            });
        });
    });
    return Promise.all(docs);
}

您可以通过删除returns 和中间docs 常量来进一步“简化”它。

function listMongoCollections(db) {
    return Promise.all(
        db.listCollections().toArray().then(docs => 
            docs.map(doc => 
                db.collection(doc.name).count().then(count => {
                    doc.count = count
                    return doc;
                })
            )
        )
    );
}

也许有了async/await,我们可以让它更容易阅读(虽然我不太熟悉):

async function listMongoCollections(db) {
    let docs = await db.listCollections().toArray();
    docs = docs.map(async doc => {
        doc.count = await db.collection(doc.name).count();
        return doc;
    });
    return Promise.all(docs);
}

这些只是示例,Mongo 可能会提供更好的解决方案。

【讨论】:

  • 由于这些是 Bluebird 的承诺,您可以使用 .map().all()(参见 this gist)。
  • 只是一个小小的批评,这是非常值得商榷的,但 IMO 忽略了 returns 绝对不会提高可读性。乍一看,好像函数什么都不返回,直到你意识到没有大括号。无论如何,这可能更像是对胖箭头语法的批评,而不是您的解决方案,但也许您应该添加一个注释,即函数肯定必须返回承诺。
  • 完全,这就是为什么我说并双引号 “简化”,而不是“提高可读性”。 ?罗伯特在评论中的要点实际上是一个更好的解决方案
  • 这是迄今为止我在任何地方看到的关于 Promise 反模式的最佳答案。谢谢。
猜你喜欢
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2020-02-28
  • 1970-01-01
相关资源
最近更新 更多