【问题标题】:Asynchronous function not waiting for Promise异步函数不等待 Promise
【发布时间】:2020-03-24 07:31:06
【问题描述】:

我编写了以下异步 node.js 函数,它通过 Mongoose 访问我的数据库,因此是一个异步函数):

function getWindSpeed(householdID){
    return new Promise(async function (resolve, _){
        const household = await Household.findById(householdID)
        resolve(stoch.norm(household.windSimulation.mu, household.windSimulation.sigma, 1))
    })
}

另一方面,我有以下函数,它也是异步的,因为既访问数据库又对数据库中的每个元素使用前面的函数:

async function getMeanWindSpeed() {
    return new Promise(async function (resolve, reject){
        let numberOfHouseholds = 0
        let averageWind = 0.0
        console.log('Begin')
        await Household.find({}, async function (error, households) {
            if(error){
                reject(error)
            }else{
                numberOfHouseholds = households.length
                for(let i = 0; i < households.length; i++){
                    const speed = await wind.getWindSpeed(households[i].id)
                    console.log(speed)
                    averageWind += speed

                }
            }
        })
        averageWind = averageWind / numberOfHouseholds
        console.log('Finish')
        resolve(averageWind)
    })    
}

如您所见,我遍历集合中的所有元素并应用 getWindSpeed() 函数,但它不会等待其完成,因为我根据 console.log(...) 调试消息得到以下跟踪:

Begin
Finish
12.2322
23.1123
(more speeds)
...

更多可能有用的信息:

  • 我在另一个异步函数中等待getMeanWindSpeed() 的结果
  • 我尝试为数据库中的每个元素返回一个硬编码值(而不是调用 getWindSpeed() 并且它工作正常,所以我猜问题出在那个函数上。

提前致谢

【问题讨论】:

    标签: node.js asynchronous es6-promise


    【解决方案1】:

    如果我们不向 .find() 传递回调,我们将返回一个 Promise,这使得代码更易于阅读。

    我们可以进一步简化函数 getMeanWindspeed,因为它成为 getAverageWindSpeed() 的简单包装器;

    例如:

    async function getAverageWindspeed() {
        let numberOfHouseholds = 0
        let averageWind = 0.0
        let households = await Household.find({});
        numberOfHouseholds = households.length
        for(let i = 0; i < households.length; i++){
            const speed = await wind.getWindSpeed(households[i].id)
            console.log(speed)
            averageWind += speed
        }
        return averageWind / numberOfHouseholds;
    }
    
    async function getMeanWindSpeed() {
        console.log('Begin')
        let averageWind = await getAverageWindspeed();
        console.log('Finish')
        return averageWind;
    }
    

    【讨论】:

    • 您的getMeanWindSpeed() 函数是反模式。如果getAverageWindSpeed() 返回一个promise,则无需将其包装在另一个promise 中。只需退回您已有的。
    • 我刚刚在上面提到过!这是一个很好的观点......我相信函数 getMeanWindSpeed 在这一点上基本上是多余的......
    • 类似地,House.find() 可能是一个能够返回承诺的数据库函数(如果没有回调传递给它)。 getAverageWindSpeed() 应该是这样修复的。
    • 这又是一个好点......这会让事情变得更干净......我只是假设如果不通过回调我们会得到一个承诺......我不是100% 确定这一点。谢谢@jfriend00
    • 现在,你明白了。只需消除 getMeanWindSpeed() 的重复副本,正如您指出的那样,现在甚至没有必要。
    【解决方案2】:

    为什么您将等待与承诺混为一谈。这是不好的做法。如果你可以使用 await 和 async 做同样的事情。请参见下面的示例。

    const fakeDelay = () => new Promise(r => {
        setTimeout(() => r("data"), 1000);
    })
    const Household = {
        findById: () => fakeDelay()
    }
    async function getWindSpeed(householdID){
        const household = await Household.findById(householdID)
        console.log()
        //stoch.norm(household.windSimulation.mu, household.windSimulation.sigma, 1)
        return household;
    }
    const main = async () =>{
        getWindSpeed().then(console.log)
    }
    main()
    

    // 通知

    异步函数getWindSpeed

    将默认承诺

    【讨论】:

    • “混合等待与承诺”这句话毫无意义。 await 仅在您等待承诺时才有用。因此,两者必须一起使用。
    • 是的.. 但在这里它没有意义。默认情况下,一切都是承诺。
    • “默认情况下一切都是承诺”也没有意义。
    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多