Code-Along: Dog Fetcher
Follow these instructions to build a website that will provide the user with some pictures of dogs.
Click here to view the Dog Fetcher Starter project. Copy the project to begin the activity.
Part One: Background
Typically, dogs play fetch. In this activity, your code is going to be playing fetch, and the things that your code will be fetching will be dogs!

The Starter Code
The starter project has quite a bit of code, but it's all HTML and CSS! In the index.html file, there are a few elements of note:
- An
<input>with anidof"num-dogs" - A
<button>with anonclickof"getDogs()" - An
<img>with anidof"loading"- This is currently hidden using CSS
- A
<div>with anidof"dog-imgs"
All of these elements will be necessary to make the website functional.
NOT WORKING: The shibe.online API
Note: the shibe.online API appears to be down. Use https://hytop.onrender.com/api/fake-api/dogs instead.
The code needs something to fetch, and luckily, there is an API that provides random pictures of shiba inu dogs! These adorable pups are also known as "shibes" in internet parlance - hence the name, shibe.online. Take a look at the homepage to learn more about how the API works.
The base url is https://shibe.online/api/shibes. For the purposes of this activity, the only relevant query parameter will be count. The response will be a JSON array of strings; each one a URL pointing to a picture of a shibe.
Putting it all together, here's an example URL: https://shibe.online/api/shibes?count=3
The response should look something like this:
[
"https://cdn.shibe.online/shibes/039e86853cb65ed16cb3823a4fd9528ae374cfec.jpg",
"https://cdn.shibe.online/shibes/6179b94f4e16762f29e69b48a45f16372b11ed72.jpg",
"https://cdn.shibe.online/shibes/e0419f6e1f00e800bada84233b0bad86723077ed.jpg"
]
Try opening one of the URLs to see the picture! Here is one of them:

The Plan
To utilize this API, the code should:
- Make a request to the base URL using
fetch- Use the
<input>to determine thecountto pass in as a query parameter
- Use the
- Extract the image URLs from the response
- Create new
<img>elements, one for each URL returned
Part Two: Button Begins 🦇
Currently, there is no JavaScript code in the project. That's bad! Start things off by hooking up the <button onclick="getDogs()"> with a new function definition.
- Open the script.js file for editing
- Define a new function named
getDogs - In the body of the function, create a new variable named
loadingImg - Set
loadingImgto grab the<img id="loading">picture- Use
document.querySelectorfor this
- Use
- On the next line, set the
style.displayof the image to"inline-flex"- This will make the loading indicator appear
At this point, run the project, click the "Get Dogs" button, and verify that the loading indicator image appears! The code should look something like this:
function getDogs() {
let loadingImg = document.querySelector("#loading");
loadingImg.style.display = "inline-flex";
}
Part Three: Fetching Two Dogs 🐕🐕
Now the button is ready, so it's time to try to get some dogs! To start, the code can ignore the <input> and just try to get two dogs.
Trying to Fetch with fetch
Use the fetch function to send a request out to the API to try to get some shibe pics.
- Make a new line in the body of the
getDogsfunction - Create a new variable named
response - Set
responseto equal a call tofetch- Pass in `
https://hytop.onrender.com/api/fake-api/dogsdogs?count=2` as the URL
- Pass in `
- Under that, create a variable named
responseJson - Set
responseJsonto a call to thejson()function on theresponsevariable - Finally, call
alertonresponseJsonto display the result
With that, run the code, click the "Get Dogs" button again, and see what happens. It might not quite work... it should display a pop-up, but there is an issue with this code:
let response = fetch(`https://hytop.onrender.com/api/fake-api/dogs?count=2`);
let responseJson = response.json();
alert(responseJson);
Catching an Error with try/catch
So something is wrong, and it may be possible to debug it, but it is also possible for the code itself to catch the error! Use the try/catch structure to try to figure out what is happening.
- Above the current variables, declare
responseandresponseJsonwithout giving them a value- This will allow the code to use them in and out of the
tryblock
- This will allow the code to use them in and out of the
- Under that, create a
try/catchstructure- Start with the
trykeyword - Then, add curly brackets
{and} - After that, add the
catch - For the
catch, add parentheses(and) - Put
ewithin the parentheses to represent the error - Finally, add another set of curly brackets
{and}
- Start with the
- Move the original variable sets into the
tryblock- Make sure to get rid of the
letbecause these already exist
- Make sure to get rid of the
- In the
catchblock, callalerton the error - Also in the
catchblock,returnfrom the function
The modified code should look something like this:
let response, responseJson;
try {
response = fetch(`https://hytop.onrender.com/api/fake-api/dogs?count=2`);
responseJson = response.json();
} catch (e) {
alert(e);
return;
}
Now, try running the project and clicking the button. It still will not work, but at least the error should appear in a pop-up! It should say the following:
TypeError: response.json is not a function
Fixing the Error with Asynchronicity
Hmm... why would response.json not be a function? The fetch call should return a Response object... or should it? What does the fetch function return again?
The fetch function returns a Promise object - so it must be awaited to yield the actual result!
- Start by adding the
asynckeyword to thegetDogsfunction definition - Next, add the
awaitkeyword in front of thefetchcall - Also, add the
awaitkeyword in front of thejson()call - Additionally, add a
finallyblock after thecatchblock - There, make the loading indicator disappear
- Use
.style.display = "none"to accomplish this
- Use
- Additionally, for testing, purposes, call
alertonresponseJson
Run the program, click the "Get Dogs" button again, and verify that some dog image URLs appear! Copy and paste one into a new tab to see a shibe like this.
At this point, the entire code in the script.js file should look something like this:
async function getDogs() {
let loadingImg = document.querySelector("#loading");
loadingImg.style.display = "inline-flex";
let response, responseJson;
try {
response = await fetch(`https://hytop.onrender.com/api/fake-api/dogs?count=2`);
responseJson = await response.json();
} catch (e) {
alert(e);
return;
} finally {
loadingImg.style.display = "none";
}
alert(responseJson);
}
Part Four: Displaying the Images
The fetch request is actually working! The JavaScript code is talking to an API and retrieving something from the internet. The next step is to display the results in a nicer way.
Prepping the Container
There is already a <div id="dog-imgs"> container in the index.html file - this will hold the new pictures of dogs. The first step will be to grab it, and clear out anything that's in it.
- Remove the
alertfrom the body of thegetDogsfunction - In its place, create a new variable named
dogImgsDiv - Use
document.querySelectorto grab the<div id="dog-imgs">and store it in the variable - Under that, set the
innerHTMLof thedogImgsDivto be""
The code for this part should look something like this:
let dogImgsDiv = document.querySelector("#dog-imgs");
dogImgsDiv.innerHTML = "";
Looping the Response
The goal is to create one picture element for each picture URL in the response. The responseJson object should be an array that stores something like this:
[
"https://images.dog.ceo/breeds/shiba/shiba-9.jpg",
"https://images.dog.ceo/breeds/shiba/shiba-10.jpg"
]
The forEach array function will be perfect for this! First, establish the loop.
- Make a new line at the bottom of the
getDogsfunction - There, call the
forEach()function onresponseJson - Between the parentheses, create a new arrow function
- It should have one parameter:
dogUrl - It should have an arrow:
=> - It should have curly brackets:
{and}
- It should have one parameter:
The loop code should look something like this:
responseJson.forEach(dogUrl => {});
Adding Each Image to the Container
Now the code is setup to run a block for every image URL retrieved from hytop.onrender.com/api/fake-api. For each of them, a new <img> element should be created and added to the dogImgsDiv container!
- Within the
forEacharrow function body, make a new line - There, create a new variable named
newDogImg - Set
newDogImgto be a new"img"element usingdocument.createElement - Under that, set the
srcofnewDogImgto thedogUrlvalue - Under that, append the
newDogImgelement to thedogImgsDivelement- Use
appendChildto accomplish this
- Use
Run the project, click the "Get Dogs" button, and verify that the dog images actually appear now! Click it a few times to see some different pairs of dogs. The code in the body of the arrow function should look something like this:
let newDogImg = document.createElement("img");
newDogImg.src = dogUrl;
dogImgsDiv.appendChild(newDogImg);
Part Five: Dynamic Number of Dogs
The final step is to actually take into account the text box - this will allow the user to grab a specific number of shibes!
- Make a new line above the
let response, responseJsonline in the body of thegetDogsfunction - There, create a new variable named
numDogsInput - Set
numDogsInputto be the<input id="num-dogs">element- Use
document.querySelector
- Use
- Under that, create a new variable named
numDogs - Set
numDogsto be thevalueof thenumDogsInputelement - Find the
fetchcall - In the
fetchURL, replace the2with the interpolatednumDogsvalue- Use
${numDogs}
- Use
Run the project, enter a number of dogs, click the "Get Dogs" button, and verify that the proper number of dogs appears!
Conclusion
Wow. There sure are some dogs in that API! In this activity, the code used fetch to grab data from an API (using an HTTP GET request) and display images from it.
By the end of the code-along, the script.js file should look something like this:
async function getDogs() {
let loadingImg = document.querySelector("#loading");
loadingImg.style.display = "inline-flex";
let numDogsInput = document.querySelector("#num-dogs");
let numDogs = numDogsInput.value;
let response, responseJson;
try {
response = await fetch(`https://hytop.onrender.com/api/fake-api/dogs?count=${numDogs}`);
responseJson = await response.json();
} catch (e) {
alert(e);
return;
} finally {
loadingImg.style.display = "none";
}
let dogImgsDiv = document.querySelector("#dog-imgs");
dogImgsDiv.innerHTML = "";
responseJson.forEach(dogUrl => {
let newDogImg = document.createElement("img");
newDogImg.src = dogUrl;
dogImgsDiv.appendChild(newDogImg);
});
}
Next Steps
Click here to see how you can make more updates to the Dog Fetcher site!