0

basically I have a big array with object values like this:

[{
  - Champion Name
  - [Another Array with Skins information]
}]

so what I want to do is run a map function inside the second array to get a value for everyone of these skins so what I did was.

const got = require('got');
const cheerio = require('cheerio');
const fs = require('fs').promises;

const getSkinData = async champSkins => {
  const data = JSON.parse(champSkins);

  const handleMap = skin => {
    return new Promise(async (resolve, reject) => {
      try {
        const name = skin.split(' ').join('_');

        const { body } = await got(`https://lol.gamepedia.com/${name}`);

        const $ = cheerio.load(body);

        const skinLink = $('.InfoboxSkin img').attr('src') || '';

        const skinInfo = {
          skinName: skin,
          skinLink
        };

        resolve(skinInfo);
      } catch (err) {
        console.error(err.message);
      }
    });
  };

  Promise.all(
    data.map(async ({ skins }) => {
      return Promise.all(
        skins.map(skin => {
          return handleMap(skin);
        })
      );
    })
  ).then(data => console.log(data));
};

module.exports = getSkinData;

but it didn't actually work, I couldn't access the data and the console.log inside the promise at the end didn't even run.

any idea how to do it or is there a better way to do it?

EDIT #1

basically 'skins' for every champ is an array of strings like:

[ 'Aatrox',          
  'Justicar Aatrox', 
  'Mecha Aatrox',    
  'Sea Hunter Aatrox'
  'Blood Moon Aatrox'
  'Blood Moon Aatrox 
  'Victorious Aatrox' ]

[ 'Ahri',            
  'Dynasty Ahri',    
  'Midnight Ahri',   
  'Foxfire Ahri',    
  'Popstar Ahri',    
  'Challenger Ahri', 
  'Academy Ahri',    
  'Arcade Ahri',     
  'Star Guardian Ahri
  'K/DA Ahri',       
  'K/DA Ahri Prestige
  'Elderwood Ahri' ] 

and skin is just every value of the array

and the value that comes back from the scraping is just a link for each skin

enter image description here

6
  • Does your function handleMap work on its own? Commented Mar 29, 2020 at 21:17
  • @abondoa it does i console logged the value of skin info and it worked perfectly fine Commented Mar 29, 2020 at 21:19
  • Can you add console.log inside your map functions to see what the skins and skin actually look like? Commented Mar 29, 2020 at 21:28
  • I edited and added more info in the question:) Commented Mar 29, 2020 at 21:33
  • An async function that returns Promise.all will result in a double promise. Commented Mar 29, 2020 at 21:35

1 Answer 1

1
const getSkinData = async champSkins => {
    const data = JSON.parse(champSkins);
    // async that returns promise is a double promise, you only need async
    const handleMap = async skin => {
        try {
            const name = skin.split(" ").join("_");
            const { body } = await got(`https://lol.gamepedia.com/${name}`);
            const $ = cheerio.load(body);
            const skinLink = $(".InfoboxSkin img").attr("src") || "";
            const skinInfo = {
                skinName: skin,
                skinLink
            };
            // changed resolve to return
            return skinInfo;
        } catch (err) {
            console.error(err.message);
        }
    };

    return await Promise.all(data.map(({ skins }) => Promise.all(skins.map(skin => handleMap(skin)))));
};

Async functions return a promise that resolves with their return value, so returning a promise from an async function is redundant and ends up causing a nested promise. Also, you don't have to use .then in async functions because you can just await the promise. Read more about Promises and async/await.

Sign up to request clarification or add additional context in comments.

4 Comments

I'm getting a very werid error saying that const { body } = await got(`ht...<omitted>... } is not iterable, any idea what that means?
i literally deleted everything in handleMap and still get the same error.
i still cant figure where the error is coming from, do you mind it if I got the project on github and linked in to you?

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.