【问题标题】:How to properly chain promises inside of a forEach loop in Javascript如何在 Javascript 中的 forEach 循环中正确链接承诺
【发布时间】:2018-02-04 09:55:18
【问题描述】:

我正在使用 mongo,需要对循环内的每个项目进行异步调用。一旦循环内的所有承诺都完成后,我想执行另一个命令,但到目前为止,循环中的承诺似乎是在循环之后的代码之后完成的。

基本上我希望订单是

循环承诺 然后 其他代码

而不是现在的样子

其他代码 循环承诺

MongoClient.connect(connecturl)
.then((client) => {
  databases.forEach((val) => {
    val.collection.forEach((valcol) => {
      client.db(val.databasename).stats() //(This is the async call)
      .then((stats) => {
        //Do stuff here with the stats of each collection
      })
    })
  })
})
.then(() => {
  //Do this stuff after everything is finished above this line
})
.catch((error) => {
}

我们将不胜感激。

【问题讨论】:

    标签: javascript mongodb promise


    【解决方案1】:

    假设您使用.forEach() 的东西是可迭代的(数组或类似的东西),您可以使用async/await 序列化for/of 循环:

        MongoClient.connect(connecturl).then(async (client) => {
            for (let db of databases) {
                for (let valcol of db.collection) {
                    let stats = await client.db(db.databasename).stats();
                    // Do stuff here with the stats of each collection
                }
            }
        }).then(() => {
            // Do this stuff after everything is finished above this line
        }).catch((error) => {
            // process error
        })
    

    如果您想坚持使用您的 .forEach() 循环,如果您并行执行操作并使用 Promise.all() 知道何时完成,则可以使这一切正常工作:

    MongoClient.connect(connecturl).then((client) => {
        let promises = [];
        databases.forEach((val) => {
            val.collection.forEach((valcol) => {
                let p = client.db(val.databasename).stats().then((stats) => {
                    // Do stuff here with the stats of each collection
                });
                promises.push(p);
            }); 
        });
        return Promise.all(promises);
    }).then(() => {
        // Do this stuff after everything is finished above this line
    }).catch((error) => {
        // process error here
    });
    

    【讨论】:

    • 顶层等待还没有准备好,那么回调需要标记为异步。
    • @Xlee - 你是对的。我在第一个 .then() 处理程序中添加了一个 async 并删除了外部异步包装函数。
    • 我正在使用你的 forEach 解决方案,你将承诺推送到数组,它似乎完全按照我的意愿工作!我认为它搞砸了,虽然我用“统计”而不是收集统计信息来获取数据库统计信息。
    • @Milos 你的不起作用的原因是你的第一个然后没有返回一个 Promise,因此被视为同步调用。我喜欢使用 Promise.all 的解决方案,因为它可以并行化您的异步任务。您也可以使用 reduce 函数来实现顺序异步任务。
    • @Xlee 首先你的意思是 mongoconnect 需要返回一个承诺还是我读错了你的评论?如果您能进一步解释一下,我将不胜感激。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    相关资源
    最近更新 更多