7

I have a website/portfolio where I display all my projects using the Github API. My goal is to create a filter for these projects, so I created a file in the root of some repositories called "built-with.json", that file exists in only two repositories just for test purpose, that is a array of technologies I used in the project (example: ["React", "Javascript", ...]). So I need to fetch the Github APi(that part it's working well), then fetch that file, and return a new Array of projects but with an "filters" key where the value is the array inside of "built-with.json". Example:

Github API return (example of just one project returning):

[{
"id": 307774617,
"node_id": "MDEwOlJlcG9zaXRvcnkzMDc3NzQ2MTc=",
"name": "vanilla-javascript-utility-functions",
"full_name": "RodrigoWebDev/vanilla-javascript-utility-functions",
"private": false
}]

New array of objects that a I need:

[{
"id": 307774617,
"node_id": "MDEwOlJlcG9zaXRvcnkzMDc3NzQ2MTc=",
"name": "vanilla-javascript-utility-functions",
"full_name": "RodrigoWebDev/vanilla-javascript-utility-functions",
"private": false,
"filters": ["HTML5", "CSS3", "JS", "React"]
}]

This is what I did:

const url = "https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created";
fetch(url)
  .then((response) => response.json())
  .then((data) => {
      return data.map(item => {
        //item.full_name returns the repositorie name
        fetch(`https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`)
          .then(data => {
            item["filters"] = data
            return item
          })
      })
    })
  .then(data => console.log(data))

But it does not work! I get this in the console:

enter image description here

Someone can help me? Thanks in advance

Note: Sorry if you find some gramatical errors, my English it's a working in progress

3
  • 1
    A couple of things here. You don't need the .then() chained onto fetch(). fetch() returns a promise. Array.prototype.map() returns an array. Put together, you end up with an array of promises. You can resolve the array of promises with Promise.all(arrayOfPs) Commented Oct 31, 2020 at 0:46
  • You need to chain a promise.all. please look at this. Commented Oct 31, 2020 at 0:47
  • You miss out a return before the inner fetch('https://raw.githubusercontent… Commented Oct 31, 2020 at 0:49

3 Answers 3

12

A couple of things here. You don't need the .then() chained onto fetch(). fetch() returns a promise. Array.prototype.map() returns an array. Put together, you end up with an array of promises. You can resolve the array of promises with Promise.all(arrayOfPs)

EDIT: After your comments and reviewing your question, I've rewritten this so that it retrieves the skills from the filtered list of repositories.

const url = `https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created`;

(async() => {
  // Final results 
  let results;
  try {
    // Get all repositories
    const repos = await fetch(url).then((res) => res.json());
    const responses = await Promise.all(
      // Request file named 'build-with.json' from each repository
      repos.map((item) => {
        return fetch(
          `https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`
        );
      })
    );
    // Filter out all non-200 http response codes (essentially 404 errors)
    const filteredResponses = responses.filter((res) => res.status === 200);
    results = Promise.all(
      // Get the project name from the URL and skills from the file
      filteredResponses.map(async(fr) => {
        const project = fr.url.match(/(RodrigoWebDev)\/(\S+)(?=\/master)/)[2];
        const skills = await fr.json();
        return {
          project: project,
          skills: skills
        };
      })
    );
  } catch (err) {
    console.log("Error: ", err);
  }
  results.then((s) => console.log(s));
})();

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

6 Comments

Your example is returnning a new Array of promises, I need a new array of github projects with the key "filters", how I reach this result?
the example is returning an array of HTTP responses. They are all 404 errors. I don't think I understand what you mean or what you see in the result.
I re-read your question. You don't identify which repos have this magic file with your "filters". Provide a repo that has that file in it and I'll retrieve it and print it's content.
@Rodrigo - there you go!
|
2

The problem was that the fetch wasn't being returned hence the .map() was returning undefined. May I suggest a solution using async-await.

const url = "https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created";

getData(url).then(data => console.log(data));
  
async function getData(url){
  const response = await fetch(url);
  const data = await response.json();
  const arrOfPromises = data.map(item => fetch(`https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`)
  );
  return Promise.all(arrOfPromises);
}

4 Comments

you didn't even change my variable name :-) LOL
I'm sorry, I did use your example as a reference. I also upvoted your answer because it was the correct one. I will delete this answer if that's a problem for you. @RandyCasburn
NO - don't delete your answer! It is just as valid as mine. I was just teasing you.
Your example is returnning a new Array of promises, I need a new array of github projects with the key "filters", how I reach this result?
1

You have multiple problems:

  1. Inside of map function you do not return any result
  2. Result of your map function will actually be another Promise (because of fetch inside).

So what you need to do:

  1. Return promise from map - as a result you will have array of promises
  2. Wait for all promises from point 1 using Promise.all

Something like this:



    var url1 = "https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created";
    var datum = fetch(url1)
      .then((response) => response.json())
      .then((data) => {
          return Promise.all(data.map(item => {
            //item.full_name returns the repositorie name
            return fetch(`https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`)
              .then(data => {
                item["filters"] = data
                return item
              })
          }));
        }).then(data => console.log(data))

9 Comments

Hey Nikitia. It worked, but the new array of objects returned is not the array of filters, but the return of fetch, see ibb.co/t4Y04gQ .I tried to pass the repsonse to json like this ibb.co/VV0XT00 but it did not work
to understand what is going on there, i would need to see what are you receiving, you could try .text() instead of .json() - maybe it will give you a clue
with .text() it worked, but it returned an string ( jsfiddle.net/gtqjna1y check the "my-website" repositorie in the returned array), I can change the string to an array, but is there some way to get it as an array? To you understand better, there are two repositories with the file "built-with.json" that I want to fetch, the repostories is my-website and border-radius-previewer, If a can make it work for these two I will create thie file inside each project to build my filter
I need to see exactly what you receiving from network, it might be that json is stringified there or something like that, you could try JSON.parse on text() and see if that works
Please, check this url: jsfiddle.net/gtqjna1y , in dev tools console check the "my-website" repositorie in the returned array, there is what exactly what I'm receiving, or you can see this screenshot ibb.co/t4Y04gQ. JSON.parse does not work because the response is not a JSON stringified but the promise object
|

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.