Home > Software engineering >  GitHub API requests to get language usage
GitHub API requests to get language usage

Time:12-21

I'm drowning in Promises trying to get a, what I thought would be simple, piece of data back from my GitHub Repos.

All I want to do is find the percentage of languages usage across each of my repositories on GitHub. I've got it working but I am pretty confident I'm miles away from doing it correctly or as succinctly as I could if I knew what I was doing. I would really appreciate any feedback on how to go about this the right way and possibly a refactor that uses more up to date methods.

Here's my code so far (which works). Ignore how I'm outputting it for now, that's just for the proof of concept.

const username = '<GH_USERNAME>' //your username here
const apiUrl = `https://api.github.com/users/${username}/repos`;

fetch(apiUrl)
.then((response) => {
    if (response.ok) {
        return response.json();
    }  
})
.then((data) => {
    languagePromises = [];
    for (let i in data) {
        let repo = data[i];
        if (!repo['fork'] && repo['language']) {
            // console.log(repo['name'], repo['language']);
            let langs = repo['languages_url'];
            languagePromises.push(fetch(langs))
        }
    }
    Promise.all(languagePromises)
    .then((responses) => { 
        let languages = [];
        for (let r of responses) {
            if (r.ok) languages.push(r.json())
        }
        Promise.all(languages)
        .then((resolved) => { 
            let languageTotals = {};
            for (langData of resolved) {
                for (lang in langData) {
                    if (!languageTotals[lang]) {
                        languageTotals[lang] = 0
                    }
                    languageTotals[lang]  = (langData[lang]); 
                }
            }
            // console.log(languageTotals);
            let sum = 0;
            for (let l in languageTotals) { sum  = languageTotals[l] }
            for (let l in languageTotals) {
                let p = (languageTotals[l] / sum * 100).toFixed(0)   '%';
                document.write(l,' ', p, '<br>');
            }
        });
    });
})
.catch((e) => {
    console.error('Error:', e);
});

Like is say. It's working but I'm basically looking for advice on how to do this properly.

CodePudding user response:

const username = 'octocat'
const apiUrl = `https://api.github.com/users/${username}/repos`;

fetch(apiUrl)
  .then((response) => {
    if (!response.ok) {
      throw new Error('Request failed')
    }
    return response.json();
  })
  .then((repos) => repos.filter(repo => !repo['fork'] && repo['language']).map(repo => fetch(repo['languages_url'])))
  .then(e => Promise.all(e))
  .then((resps) => resps.filter(r => r.ok).map(r => r.json()))
  .then(e => Promise.all(e))
  .then((resolved) => {
    console.log(resolved)
    const languageTotals = {};
    for (const langData of resolved) {
      for (const lang in langData) {
        if (!languageTotals[lang]) {
          languageTotals[lang] = 0
        }
        languageTotals[lang]  = (langData[lang]);
      }
    }

    let sum = 0;
    for (const lang of languageTotals) {
      sum  = lang
    }
    for (const lang of languageTotals) {
      let p = (lang / sum * 100).toFixed(0)   '%';
      document.write(l, ' ', p, '<br>');
    }

  })
  .catch((e) => {
    console.error('Error:', e);
  });

CodePudding user response:

Here's an example that cleans/reduces a lot of your code:

const apiUrl = `https://api.github.com/users/${username}/repos`;

fetchRepos(apiUrl)
  .then((data) => {
    return (data
      .filter(repo => !repo.fork && repo.language)
      .map(repo => ghFetchJson(repo.languages_url))
    )
  )
  .then(languageResults => {
    const languageTotals = new Map();
    for (const langData of languageResults) {
      for (const [lang, count] of Object.entries(langData)) {
        languageTotals.set(lang, (languageTotals.get(lang) ?? 0)   count);
      }
    }
    const sum = Array.from(languageTotals).reduce((acc, cur) => acc cur[0], 0);

    for(const [language, count] of languageTotals) {
      const p = (count / sum * 100).toFixed(0)   '%';
      console.log('%s: %i', language, count);
    }

  });
}).catch((e) => {
    console.error('Error:', e);
});

async function ghFetchJson(url) {

  const res = await fetch(url);
  return res.json();

}
  • Related