How to Use Javascript “Fetch-Chaining” with the Pokemon API to Get that Deep Data crashdaddy Follow Mar 30 · 6 min read

Gotta Catch All the Data!

If you’re reading this, then you’ve probably been working with APIs already (and probably the pokeAPI in particular) and understand something about API fetches and promises.

Here’s what I did using this technique (and you can, too!)

The starting point is to know where you want to start. Are you going to show a list of all pokemon types and let the user filter by that? Or do you want to provide a list of all regions and show what pokemon are native to that region?

We’re going to go the first route, filtering by type. Here’s a link to a project that filters by regions! That’s not made by me, but by another developer (she’s from Canada — you wouldn’t know her).

This is how you get a list of all pokemon types:

//

// Get all the different "types" of Pokemon

// and make a button out of each type

// to filter the data

// const getAllTypes = () => {

fetch(‘https://pokeapi.co/api/v2/type')

.then(res=> res.json())

.then(pokemonType => {

pokemonType.results.forEach(function(typeOfPokemon){

addButton(typeOfPokemon);

})

})

}

That function calls the Pokemon API to get a list of all the different types, then creates a button for each one. Here’s the link to the API results you’re calling.

Just for you, here’s the function to add the buttons to your html page:

//

// This function adds a button for every different pokemon type

// that when clicked will summon all pokemon of that type

// const addButton = (pokemonType) => { let select = document.getElementById(“buttons”); let button = document.createElement(“button”); button.innerHTML = `${pokemonType.name}`; select.append(button); button.addEventListener (“click”, function(){ this.parentElement.querySelectorAll( “.clicked” ).forEach( e => { getPokemonByType(pokemonType.url)}); }

All you need to make that work is an HTML page with a DIV that has the ID “buttons.”

And just like that, you have a list of all the different types. But here’s where it gets tricky. Because say you want your webpage to deliver a picture of each pokemon of whatever type was written on the button the user clicked.

Well, here’s the data that’s returned when you call the API for a specific type of pokemon:

As you can see, it’s basically just a link that has a bunch more links in it

Here’s the link to that data.

What you’re getting is the specific details that apply to that particular “type” of pokemon; like what attacks they have, defenses, moves, etc. Then it has a list of URLs that lead to more data on each individual pokemon of that type!

So if you click the button and you get this back, what are you supposed to do with it?!? This is a nightmare!

If you follow the link in that first listing you get this:

This rabbit hole just keeps getting deeper!

Here’s the link to this data!

Notice how now it’s returned a bunch of data about the individual pokemon, but where are the pictures?

Relax, they’re right here!

So finally we found our pictures, but how are we going to get them to display when the user just clicked a button for the “type” of pokemon?

That’s where fetch-chaining comes in. Basically, you just write a function that calls that list in the picture above, then goes through that list and calls each of the URLs in that list, then goes through each of those URLs to find the picture of the pokemon.

And I’ma show you how to do it right now.

//

// Returns all the Pokemon of a certain type specified

// by the buttons on the nav panel on the left side

// const getPokemonByType = (typeURL) => { fetch(typeURL)

.then(res => res.json())

.then(pokemonType => { HTMLstr =””;

document.getElementById(“output”).innerHTML=HTMLstr;



pokemonType.pokemon.forEach(function(pokemon){

fetchPokemonData(pokemon.pokemon.url);

}) showPokemonTypeDetails(pokemonType); }) .catch((error) => {

console.error(‘Error:’, error);

}); }

For this to work, your HTML page needs a DIV with the ID of “output” and we’re using a global variable HTMLstr to determine what’s going to be shown in that DIV.

Note for Beginners: to declare a variable as “global,” just declare it outside of any functions.

Ex: let HTMLstr = “”;

That’s all there is to that.

What’s going on in that function is that when you clicked one of the buttons you created earlier, that button called this function with the URL to a particular type of pokemon.

This function “fetch”es the URL, then when it gets a response it calls the response “pokemonType”.

Here’s where the fetch chaining comes in, because this part here:

pokemonType.pokemon.forEach(function(pokemon){

fetchPokemonData(pokemon.pokemon.url);

})

tells it that for EACH pokemon on that list, we are going to give it the variable name “pokemon” then we’re going to call its own distinct URL. I put the second fetch to call each URL in another function just for clarity. As you can see, it’s called “fetchPokemonData(pokemon.pokemon.url)”.

Here’s what it looks like:

//

// This routine calls each pokemon of the selected type,

// and outputs its picture to the main output in the center

// const fetchPokemonData = (pokemon) => { fetch(pokemon)

.then(response => response.json())

.then(pokeData => { if(pokeData.sprites.front_default){ HTMLstr += `<div class=”pokeDex” id=”${pokeData.id}” onclick=”showDetails(${pokeData.id})” style=”float:left;border-radius:5%;” title=”${pokeData.name}”><img src=”${pokeData.sprites.front_default}” style=”max-height:96px;”></div>`; } document.getElementById(“output”).innerHTML=HTMLstr; })}

This function is just like any other; it fetches the URL, then it parses the response, then we call the response “pokeData”.

Then we check to see if there’s a picture there at all, by saying:

if(pokeData.sprites.front_default)

That’s just checking to see if a frontal view of that pokemon exists. If it doesn’t, the function’s just going to skip that pokemon.

But if there is a picture, then we’re going to get that picture’s URL, then add it to the output string:

HTMLstr += `<div style=”float:left;border-radius:5%;” title=”${pokeData.name}”><img src=”${pokeData.sprites.front_default}” style=”max-height:96px;”></div>`

All those little “pokeData” references are to the other values that are returned by the fetch call, because it returns ALL the data, not just the image url. This code is just going to make a little “baseball card” with the pokemon’s picture on it, and when the user hovers over it they’ll see its name.

You can add a “onclick” to the DIV so that when the user clicks it something else will happen; it can show more details, animate the picture, select it for some further use — the possibilities are pretty endless.

If you’ve been able to follow along with all this, then you should have a basic — well, not a pokeDEX, exactly, but more like a pokePhotoAlbum. I made it basic just to highlight the fetch-chaining component. Once you’ve got the hang of that, you’ll be pretty unstoppable.

Make Pikachu Happy