从使用多个异步调用的函数返回

问题描述 投票:0回答:1

所以基本的想法是编写一个方法来废弃网页以获取包含产品评级的JSON数据。然后在几个域(.de,.uk,.fr,.nl等)上多次调用此方法以收集所有评级。

所以我最终用scrapWebPage方法废弃单页:

const scrapWebPage = async (countryAppData, productNumber) => {
    const shopUrl = `https://www.shopExample.${countryAppData.countryCode}/?q=${productNumber}`
    const avoidCORSUrl = 'https://allorigins.me/get?url=' + shopUrl + '&callback=?'

    return await axios
        .get(avoidCORSUrl, {xmlMode: false, normalizeWhitespace: true})
        .then(response => {
            const $ = cheerio.load(response.data)
            let scrapedWebPageJson

            contentForParsing = $("script").get().children[0].data                   
            scrapedWebPageJson = JSON.parse(contentForParsing)

            return scrapedWebPageJson
        })
}

scrapWebPage还包含一些解析来返回我想要的一些JSON数据 - 它正确解析(测试了这个)并返回Promise。

但后来我想在多个域上调用这个方法,所以我创建了getProductDataFromManyDomains

const getProductDataFromManyDomains = (productNum) => {
    let prodData = {
        reviews: []
    }

    const appCountries = [
        {countryCode: 'nl'}, 
        {countryCode: 'pl'},
        {countryCode: 'de'}
    ]

    appCountries.forEach(async countryApp => {
        let countryData = {}

        let parsedWebPage = await scrapWebPage(countryApp, productNum)

        countryData.countryCode  = countryApp.countryCode
        countryData.ratingCount  = parsedWebPage.aggregateRating.ratingCount
        countryData.ratingValue  = parsedWebPage.aggregateRating.ratingValue
        countryData.reviews      = parsedWebPage.reviews   

        prodData.reviews.push(countryData)
    })

    return prodData
}

现在我在填充之前收到prodData ...而我想收到实际数据(填充prodData)。

我不确定如何在填充之前构建这个getProductDataFromManyDomains方法来实际返回数据而不是prodData。那可能吗?或者这里处理类似的东西有什么好的模式?

javascript asynchronous promise async-await axios
1个回答
2
投票

使用for循环而不是.forEach()for循环将暂停等待,.forEach()循环不会。这是因为你传递给async.forEach()回调将返回一个承诺,但是.forEach()并不是为了做任何事情而设计的,所以它不会在继续循环之前等待它解决,而是使用forawait循环。

然后,getProductDataFromManyDomains()将需要是async并将返回您最终结果的承诺。

async function getProductDataFromManyDomains(productNum) {
    let prodData = {
        reviews: []
    }

    const appCountries = [
        {countryCode: 'nl'}, 
        {countryCode: 'pl'},
        {countryCode: 'de'}
    ]

    for (let countryApp of appCountries) {
        let countryData = {}

        let parsedWebPage = await scrapWebPage(countryApp, productNum)

        countryData.countryCode  = countryApp.countryCode
        countryData.ratingCount  = parsedWebPage.aggregateRating.ratingCount
        countryData.ratingValue  = parsedWebPage.aggregateRating.ratingValue
        countryData.reviews      = parsedWebPage.reviews   

        prodData.reviews.push(countryData)
    })

    // this will be the resolved value of the promise that
    //   getProductDataFromManyDomains() returns
    return prodData;
}

// usage
getProductDataFromManyDomains(productNum).then(result => {
    console.log(result);
});

您也可以并行运行多个请求,而不是一次运行多个请求,但由于您最初尝试让代码一次执行一个,我向您展示了如何执行此操作。

如果你想并行执行它们,你只需在数组中累积promises并使用Promise.all()知道它们何时完成,你就不会await请求。

这是使用.map()Promise.all()并行运行请求的代码版本:

function getProductDataFromManyDomains(productNum) {
    let prodData = {
        reviews: []
    }

    const appCountries = [
        {countryCode: 'nl'}, 
        {countryCode: 'pl'},
        {countryCode: 'de'}
    ]

    return Promise.all(appCounteries.map(countryApp => {

        return scrapWebPage(countryApp, productNum).then(parsedWebPage => {
            let countryData = {}
            countryData.countryCode  = countryApp.countryCode
            countryData.ratingCount  = parsedWebPage.aggregateRating.ratingCount
            countryData.ratingValue  = parsedWebPage.aggregateRating.ratingValue
            countryData.reviews      = parsedWebPage.reviews 
            return countryData;         
        });
    })).then(results => {
        // put results into prodData and make that the resolved value
        prodData.reviews = results;
        return prodData;
    });
}

getProductDataFromManyDomains(productNum).then(result => {
    console.log(result);
});
© www.soinside.com 2019 - 2024. All rights reserved.