Mongoose exec() 没有正确等待

Posted

技术标签:

【中文标题】Mongoose exec() 没有正确等待【英文标题】:Mongoose exec() does not await properly 【发布时间】:2020-11-23 13:46:12 【问题描述】:

由于某种原因,exec() 没有在我的代码中等待:

    let team = <SOME TEAM NAME> //putting manually for testing
    let results = []

    TeamModel.find( name: team )
        .exec(async (err, docs) => 
            if (err)
                return res.send(Response("failure", "Error occured while retrieving fixtures"))
            
            for(let i = 0; i < docs.length; i++)

                let doesExist = await FixtureModel.exists( leagueName: docs[i].leagueName )

                if (doesExist) 
                    let query = FixtureModel.find( leagueName: docs[i].leagueName, $or: [ homeTeam: team ,  awayTeam: team ] )
                    await query.exec((err2, docs2) => 
                        if (err2)
                            return res.send(Response("failure", "Error occured while retrieving fixtures"))

                        docs2.forEach((doc2, index) => results.push(doc2.toObject()))
                        console.log('during await') //Executes second
                    )

                    console.log('after await') //Executes first
                
                else  //This section is not required
                    let result = await Communicator.GetFixturesFromLeague(docs[i].leagueId)

                    result.api.fixtures.forEach((fixture, index) => 
                        let newFixture = new FixtureModel(
                            fixtureId: fixture.fixture_id,
                            leagueId: fixture.league_id,
                            leagueName: fixture.league.name,
                            eventDate: fixture.event_date,
                            statusShort: fixture.statusShort,
                            homeTeam: fixture.homeTeam.team_name,
                            awayTeam: fixture.awayTeam.team_name
                        )

                        newFixture.save()
                        results.push(newFixture.toObject())
                    )                    
                          
            

            console.log(results)
            res.send(Response("success", "Retrieved fixtures", results))
        )

结果看起来像这样:

after await
[]
during await

因此,在向其中添加值之前会发送一个空的结果数组。我不确定我在这里缺少什么。

【问题讨论】:

因为当query.exec 承诺被解决时代码继续,而不是在回调完成执行时。尝试return docs2.forEach((doc2, index) =&gt; results.push(doc2.toObject()))docs2 = await query.exec() 然后docs2.forEach... @dikuw 我怀疑可能是这种情况。尝试了您的解决方案,但仍然无效 query.exec() 仅在未通过回调时返回 Promise。 【参考方案1】:

如果有人想知道,这是一种解决方法。当 forLoop 完成绕过 async/await 的需要时,在 exec() 回调中发送响应。

 if (doesExist) 
                    let query = FixtureModel.find( league_name: docs[i].leagueName, $or: [ homeTeam:  team_name: team ,  awayTeam:  team_name: team ] )
                    await query.exec((err2, docs2) => 
                        if (err2)
                            return res.send(Response("failure", "Error occured while retrieving fixtures"))

                        docs2.forEach((doc2, index) => results.push(doc2.toObject()))
                        
                        if(i + 1 == docs.length)
                            return res.send(Response("success", "Retrieved fixtures", results))
                        
                    )
                

【讨论】:

恢复到计划 A 并写 let docs2 = await FixtureModel.find(.......).exec(); 并将 res.send(Response('success', 'Retrieved fixtures', results)); 留在 for 循环之外的麻烦更少。同样,let docs = await TeamModel.find( 'name': team ).exec();. 这两个 await 可以正常工作,您可以输入try /* everything */ catch(error) res.send(Response('failure', 'Error occurred while retrieving fixtures')); 。这将捕获/处理意外错误,而不仅仅是当前代码中的这两个特定错误。

以上是关于Mongoose exec() 没有正确等待的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose 中的 Model.findById() - 异步/等待 [重复]

countDocuments Mongoose 的问题:它实际上并没有等待回调函数执行

Mongoose - find(,cb) 和 find().exec(cb) 有啥区别?

Mongoose:“.find(...).exec(...).then(...).catch(...).finally 不是函数”使用蓝鸟?

Mongoose find().exec() 承诺问题 [重复]

有没有办法在不等待命令完成的情况下使用 shell_exec ?