DEV Community

Bessy Clarke
Bessy Clarke

Posted on

Fetching & Fetching

After a change of pace in my Flatiron program, I'm finally nearing the end of the Javascript module. We were tasked with building a single-page application, using HTML, CSS, and plain old Javascript on the frontend with a Ruby On Rails backend. The inspiration behind my project was my newfound obsession with Dungeons & Dragons. I play weekly and I've really enjoyed getting into character and expanding who my character is throughout our sessions. I play with a group of five people. When we were in the early stages of choosing our characters, we got together and were told to pick characters that complemented each other's skill set. So, you definitely want someone on your team who maybe is a skilled fighter, but you'd also want someone who can use magic to heal other players after intense fights.

I built a Dungeons & Dragons character creator that lets you create parties and add characters to a party and see them laid out. I used the handy dandy DnD API to fetch their data and use it in my project. I made multiple fetch requests to different endpoints. I then used this fetched data to render information to the DOM while leaving the HTML file pretty barebones.

Fetch is a pretty cool Javascript function and it can be used in a plethora of ways to make very useful apps. There are so many great APIs available and being able to use fetch opens their data to developers for use in applications.

Fetch() is an AJAX technique that has been abstracted into a easy to use function. AJAX stands for Asynchronous JavaScript And XML. AJAX uses a XMLHttpRequest object to communicate with servers. It allows us to render HTML and CSS, while giving us just enough time to render Javascript quickly and behind the scenes without the user growing inpatient.

In my project, I use several fetch requests to the DnD API to gather the names of character races, classes, alignments, and weapons.

    static getSpecies() {
        fetch('https://www.dnd5eapi.co/api/races')
        .then(response => response.json())
        .then(data => {
            // console.log(data)
            this.addSpeciesToDrop(data)
            // debugger
        })
    }
Enter fullscreen mode Exit fullscreen mode

When we use fetch() we pass in the URL of the data we're trying to retrieve. What comes back in this round of the method is called a Promise. This Promise does not send the actual data. Rather it returns the state of that data. Promises can have three states: pending, fulfilled, rejected.

    [[PromiseState]]: "fulfilled"
    [[PromiseResult]]: Response
Enter fullscreen mode Exit fullscreen mode

Once we have our fulfilled promise, we chain on a .then() method.

  fetch('https://www.dnd5eapi.co/api/races')
  .then(response => response.json())
  Promise {<pending>}
 __proto__: Promise
 [[PromiseState]]: "fulfilled"
 [[PromiseResult]]: Object
 count: 9
 results: (9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, 
 {…}, {…}]
__proto__: Object

Enter fullscreen mode Exit fullscreen mode

This first .then() method starts to give us data that we can start to look through. We can see that it gives us a count of the data we're working with. In my example, I get an array of objects. Each object is made up of an index, a name for the data, and the URL of where it's located in the API. I also take the response received from the .then() call and turn it into JSON (Javascript Object Notation), which tells JavaScript to render this data into nested objects.

results: Array(9)
0: {index: "dragonborn", name: "Dragonborn", url: "/api/races/dragonborn"}
1: {index: "dwarf", name: "Dwarf", url: "/api/races/dwarf"}
2: {index: "elf", name: "Elf", url: "/api/races/elf"}
3: {index: "gnome", name: "Gnome", url: "/api/races/gnome"}
4: {index: "half-elf", name: "Half-Elf", url: "/api/races/half-elf"}
5: {index: "half-orc", name: "Half-Orc", url: "/api/races/half-orc"}
6: {index: "halfling", name: "Halfling", url: "/api/races/halfling"}
7: {index: "human", name: "Human", url: "/api/races/human"}
8: {index: "tiefling", name: "Tiefling", url: "/ap
Enter fullscreen mode Exit fullscreen mode

We then chain one more .then() call.

  static getSpecies() {
        fetch('https://www.dnd5eapi.co/api/races')
        .then(response => response.json())
        .then(data => {
            this.addSpeciesToDrop(data)
        })
    }
Enter fullscreen mode Exit fullscreen mode

We can finally start to write code that lets us use this data in the third .then() call. In the above example, I use an arrow function to call another function. I wrote a separate method that takes in the data sent back from the fetch request as an argument and use this data to append the names of the species into a dropdown menu. And just like that, we can gather data from an external source and use it to populate our own personal applications.

Along with letting us use data from external sources in our apps, fetch() also lets us use this same method, with some variation, to send data back to our APIS. I created an API to hold my information on parties and their corresponding characters. So, to save those characters into my database, we need to let the fetch method know that we're sending a "POST" request. By default, fetch uses the HTTP verb "GET".

let character = {
                name: name,
                race: race,
                character_class: characterClass, 
                alignment: alignment,
                primary_weapon: primaryWeapon, 
                secondary_weapon: secondaryWeapon,
                // party_id: partyId
            }
            fetch("http://127.0.0.1:3000/characters", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Accept": "application/json"
                  },
                body: JSON.stringify(character)
            })
            .then(resp => resp.json())  
            .then(character => {
                alert("Character has been created!") 
                let char = new Character(character.id, character.name, character.race, character.character_class, character.alignment, character.primary_weapon, character.secondary_weapon)
Enter fullscreen mode Exit fullscreen mode

I created an object that holds the information I'm using to instantiate my character. In my case, I'm instantiating each character with a name, race, character class, alignment, and two weapons. We include a "Header", which tells the method two things. The format the content we're sending back is in, and what data form to accept. Headers can be used to include API authentication keys, that is if your API has restrictions on how it's used, or it can even include user data for cookies. I then use that object set before the fetch method to pass it into the body. Here, I turn this object into JSON so that javascript can properly read and render this data. After chaining on our two .then() calls, I instantiate my character object and let the user know that the character creation was successful!

Fetch is a great AJAX tool that has simplified the way we can talk to servers and retrieve desired information from them. I initially had a little trouble with fetch, specifically, working with the data, but by the end of this project, I'm looking forward to working with more APIs to build different projects!

Top comments (0)