1

Hey I have written this code in node js

async function getUdemydata(){

    try{
        var finalData = []
        const res = await axios.get(baseUrl)
        const $ = cheerio.load(res.data);

        $('div[class="content"]').each(async (i,el) =>{
            const courseTitle = $(el).find("a").text()
            const aa = $(el).html() 
            const courseUrl = await getCoupenCode($(el).find("a").attr("href"))
            const courseDescription = $(el).find(".description").text().trim()
            const courseImage = await formateImageUrl($(el).find(".image").html())
            var dataObj = {
            "title": courseTitle,
            "description": courseDescription,
            "image": courseImage,
            "link": courseUrl
            }
            finalData.push(dataObj);
            console.log('appended');
        })
        return (finalData);
    } catch(error){
        console.error(error);
    }

}

(async()=>{
    var rs = await getUdemydata();
    console.log(rs);
})()

When I call the getUdemydata() function only the empty array is printed after that appended which is inside the function is being printed what should I change in the code so that the function will return the final array

1 Answer 1

2

The definition of .each is as follows:

each<T>(fn: (i: number, el: T) => boolean | void): Cheerio<T>

It is not Promise-aware, so does not await the async function you supply as its parameter.

Remember that an async function is just a normal function that returns a Promise, so you could map these function calls, ending up with an array of Promise, then wait for them all.

// var finalArray = [] // <-- NO
const promises = $('div[class="content"]')
    .toArray()
    .map(async (el,i) => {
        // same body as `each` in your code
        // except, don't push into `finalArray`
        // just return your value

        // finalData.push(dataObj); // <-- NO
        return dataObj;
    });
const finalArray = await Promise.all(promises);

or if the parallelism of running all those promises at once is too much, then the documentation suggests that a Cheerio is Iterable, so just loop over $('div[class="content"]') with a normal

for(const el of $('div[class="content"]')) { //...
Sign up to request clarification or add additional context in comments.

2 Comments

...as an aside, bearing in mind that every other higher-order function over arrays tends to call its selector with index as the 2nd parameter, the parameter-order of .each(index, element) bucks the trend in a "set-you-up-to-fail" kind of way
@AnishGowda I made an edit to the code because it is not necessary to push items into finalArray

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.