Fetch API Exercises

Getting Setup with the Practice Exercises

To get setup with these practice exercises:

  1. If you have not already downloaded the practice files, you can get them from github.com/zgordon/javascript-explained

  2. Open the folder "05-fetch-api." It should have a "starter" folder and a "completed" folder.

  3. Open the "starter" directory in your code editor

  4. Open the "starter/index.html" in your web browser and open the console for testing

Practice Exercises

  1. Write out a basic Fetch API call to the URL https://dog.ceo/api/breeds/image/random usingfetch() .

  2. Add .then() to the fetch() call and convert the response to JSON

  3. Add another .then() to log the data to the console.

  4. Add a .catch() statement that displays any errors that may occur. Change the domain name in the URL from dog.ceo to dog2.ceo. This should cause an error message to display.

  5. Move the URL from inside the fetch() call to its own variable called url. Then pass the url variable into the fetch() call.

  6. Inside of the second .then() statement, after the console log of the data, log out markup for an image like so: <img src="${data.message}" alt="Random photo of a dog" />

  7. Now instead of logging the image markup to the console, have the image of the random dog display on the page before the end of the container div.

  8. Create a function called getRandomDogPhoto() that returns a fetch request to the following URL: https://dog.ceo/api/breeds/image/random. Make sure the entire fetch request is being returned.

  9. Create an async function called init()(). Inside of this function create a variable called data that awaits getRandomDogPhoto() to return the data. After the data is returned, log the value of the data to the console inside of init(). Make sure to call init() to test.

  10. Create a new function called renderDogPhoto(url) that takes the URL for a dog photo and displays it on the page before the end of the container div. Call renderDogPhoto()

    inside of the init() function right after the getRandomDogPhoto() function. Make sure to pass the correct value of the url to the dog photo into the renderDogPhoto() function (i.e. data.message not just data). If done correctly, a photo of a dog should display on the page.

  11. Two new functions have been added, loadSpinner() and removeSpinner(). Call loadSpinner() before you await the dog photo in the init() function. Then call removeSpinner() after you have received the data and before you display the dog photo. If done correctly, you should see a spinner load while waiting for the dog photo to load.

  12. Before the init() function, select the button with an ID of load-photo and assign it to a variable of button. Then, inside of the init() function, attach the handleButton function as an event listener to the button. Then, inside of the loadSpinner() function, set the button to disabled button.disabled = true. Finally, load the img variable inside of the button before the text button.insertAdjacentHTML( `afterbegin`, img ). This will cause the loading animation to appear inside of the button. Test the animation. When you click on the button it should become disable and display the loading animation inside the button. Then the button should disappear once the image loads.

  13. Make a fetch request to the following Foreign exchange rates API with currency conversion: https://api.exchangeratesapi.io/latest. Log out the results of the query.

  14. Move the fetch request to it's own function called getRates() that returns the Fetch Promise. Make sure the fetch returns the data and does not log it to the console. Create a new async function called init() with a variable called exchange that awaits getRates() and then logs exchange to the console. Test by calling init() and make sure you have the same results as before.

  15. Create a function called loadDropDown(exhange.rates) that loads a select field with an option for each of the rates. Call the function inside of the init() function. You may need to use a for in loop to iterate over the rates object. If done correctly a drop down field should appear with each of the rates in it.

    let markup = `<select id="rates">`
    markup += <option value="1">Choose Currency</option>;
    for (let rate in rates) {
    markup += `<option value="${rates[rate]}">${rate}</option>`
    markup += `</select>`
  16. Before the end of the loadDropDown() function, attach a "change" listener to the select field that logs out the value of the selected field whenever there is a change. Make sure that the conversion rate we display is a number with two decimal points. You can do this in a two part process like so: parseFloat( rate ).toFixed(2). Make sure your logRate() function is updated to display the correct rate format.

    function loadDropDown() {
    // Code from before
    const selectField document.querySelector( `#rates`)
    selectField.addEventListener( `change`, logRate)
    function logRate() {
    // Will need to convert this to two decimals
    console.log( this.value )
  17. Inside the init() function, create a base variable with a value of EUR that will serve as the currency we are converting from. Now, modify the getRates() function to take a "base" parameter that sets what currency we are converting from. The format will look something like below. Try changing the base from EUR to USD and you should see the conversion rates change.

    function getRates(base) {
    return fetch(`https://api.exchangeratesapi.io/latest?base=${base}`)
    .then(response => response.json())
    .catch(error => console.error(error));
  18. Update the user interface so that it displays the currency drop down inside the .dropdown container. Then make sure the message looks like this: 1 BASE = XX.XX. This will involve creating a loadBase(base) function that sets the .innerHTML of the .base container to the base. You will also need to update the logRate() function to update the .innerHTML of the .rate container to the proper rate.

  19. Now we will add the currency name to the results of our converter. Inside of the logRate() function create a new variable called currencyContainer and set it to the span with a class of .currency. Then create a variable currency and set it equal to the value of the currently selected option in the rates dropdown. You can do this with a selector like this: document.querySelector(`option[value="${this.value}"]`). Finally, set the .innerHTML of the .currencyContainer equal to the value of the currency. This should result in the currency name being displayed next to the rate.

  20. Setup a free account and get an API Key for wordsapi.com. It will take you to rapidapi.com to do this. Once you are signed up you can find your API key here: rapidapi.com/dpventures/api/wordsapi. Look inside the field for X-RapidAPI-Key. This is your API key. You can copy for use in your code. Set your API key as the value for the apiKey variable and see it logged to the console.

  21. Set the value of apiURL to https://wordsapiv1.p.rapidapi.com/words. Then set the value of apiKey to the value of your your WordsAPI API key. Finally set the value of word to a word you want to lookup. This example will use the word soliloquy. Last, write a fetch request to ${apiURL}/${word}. This should give you a a 401 (Unauthorized) error. We will fix this in the next step.

  22. Add your apiKey again. Then update the fetch() request to pass a second parameter after the URL that looks like the following example below. This will make sure your apiKey is sent with the request. Test in the browser to make sure you get a valid data response back with information about the word.

    fetch(`${apiURL}/${word}`, {
    headers: {
    "x-rapidapi-host": "wordsapiv1.p.rapidapi.com",
    "x-rapidapi-key": `${apiKey}`
  23. Add an event listener to the form with the ID of word-search. When the form is submitted, stop the default behavior and call a function called lookupWord(). Have this function get the value of the input filed and make the fetch call to get the results from the word lookup. Log the results to the console. Look over the results of the request to get an idea of what information you are getting back.

  24. In this step we will display an error message if a word is not found. Inside the first .then() call, write a conditional statement that checks to see if res.status is equal to 404. If it is, then set the value of the results.innerHTML equal to something like <p>Word not found!</p>. Make sure after the conditional statement you still return the value of res.json(). Test this with a made up word and you should see the error message.

  25. Write a new function called displayDefinitions(definitions) that takes an array of definitions and logs them to the page as an unordered list inside of the results div. Call the function inside the fetch() request, after you log the results to the page. Remember to only pass in data.results to the function. The results should include both the part of speech as well as the definition. The final result should look like (part of speech) definition.

  26. Add a loading animation so while the word is being looked up, the button becomes disabled and displays the loading animation from exercise 12. Once the results are loaded, remove the loading animation and remove the disabled attribute on the button.

  27. Rewrite exercise 26 to use async and await.

  28. Setup an async fetch request to the following WordPress API endpoint: https://dev-js-explained-api.pantheonsite.io/wp-json/wp/v2/posts. Log the results to the console.

  29. Write a function called displayPosts() that takes the array of posts and lists them out in an unordered list with markup like this for each post: <li><a href="#" data-id="${post.id}">${post.title.rendered}</a></li>

  30. Attach an event listener to each of the post title links after they are rendered to the page. When the user clicks on the title of the post, it should remove the list of posts and just display the post.title.rendered and post.content.rendered for that post. As a bonus challenge, include a link above the title that let's you return to viewing all of the posts. This final exercises is meant to be a bit of a challenge so feel free to look at the final code for help!

What Next?

Hopefully at this point you feel comfortable making API requests and converting them to async requests. You should also feel comfortable doing things with the data like modifying content on the page.

For additional practice you can try extending any of these exercises above to do more. You can also try getting data from other APIs.

Next up we are going to look at taking everything we have learned so far and combining it all into a final project.