Playing fetch with JavaScript
For our Phase 4 project at Flatiron school, we were tasked with creating a Single Page Application built using JavaScript on the front end which communicates with a backend API built with Ruby on Rails.
During my time at Flatiron school, I’m always thinking about what I want to do for my next project in the back of my mind. At a recent family gathering, a few of us were debating what would be the best basketball starting line-up of all time. A tradition of basketball runs deep in my family so this is not the first time that we tried to hash this out. After some debate, we ended up taking things a step further and we each drafted our own teams. This is definitely some basketball dork way to spend time with your family but it lead me to my idea for my Phase 4 project.
In this application, the user will be able to create teams and draft players to each team. Each teams roster is displayed at the top of the page and a draft board of all the players selected is visible at the bottom of the page. The user can choose to remove player or a team at any point. If the user chooses to remove a team, the players from that team will also be removed from the draft board.
While this entire phase of the course has been a challenging, I want to focus on something that took me a while to wrap my head around. That is the communication between the Javascript portion of the application(the frontend) and the Ruby on Rails portion of the application(the backend). More specifically, I want to focus on the fetch requests made on the frontend.
In order to handle the frontend of an application with javaScript and handle the backend with Ruby on Rails, the two sides need to communicate. Saying the backend of the application was built with Rails means that the Rails portion of the application is responsible for providing the API data needed for the application to run. This backend set up is very similar to an application built completely with Rails. The main difference is that instead of rendering different views, like we would in an application built entirely with Ruby on Rails, we render JSON API data for the front end to operate on.
A fetch requests is a form of AJAX which is short for Asynchronous JavaScript and XML. Running code asynchronously allows you execute a block of code that might take time to process without stopping the entire file from executing. With AJAX we can interact with the server and update the DOM without the page having to reload. Asynchronous processing creates a speedier user experience. The XML piece of AJAX refers to how data was commonly formatted in the past to be sent through the browser. These days, data is most often sent in the form of JSON which stands for JavaScript Object Notation. Because browsers only work with text, JSON data is technically a string. But the beauty is that JavaScript knows how to turn that JSON strings into an object.
Lets connect the dots and dive into the details of a fetch request. With this fetch request example, we are looking to “fetch” all the data pertaining to all of the teams stored in the backend.
A fetch method requires an API url to be passed in as an argument which allows us to handle the resources that are contained within the URL. Here, we are passing in a variable set to the Rails web server url with the “/teams” endpoint. This is telling the fetch request to go into our Rails server backend and access the data provided from the Team index controller action. This seems pretty simple right? Let’s see what this returns to us.
We’re not going to dive too deep into promises but basically a promise is a representation what an object value will eventually become before an asynchronous operation has completed. So in order for our application to run smoothly during a fetch request, we are returned a promise. The initial state of a promise is pending until it is fulfilled. If we successfully receive our data from the backend, our promise will then be resolved state. If the promise is unsuccessful, it be in a rejected state. Once a promise is in a resolved state, we receive a response object.
A response object represents an entire HTTP response which isn’t the JSON response body that we need but we’re getting closer. To extract the JSON data, we can chain a method onto the promise which is another form of using callback function. The nice thing about chaining is instead of passing the callback function in as an argument, we can just attach a chained callback to the promise response. Here, our chained method is responsible for pulling that JSON date from the response object. This returns another promise but this promise will resolve in the parsed JSON data that we want for the front end of our application!
However, we should also be prepared to handle unsuccessful fetch requests. One way to do that is by chaining a .catch statement onto the final .then statement to log an error message.
Now we are set up to handle unsuccessful fetch requests. However, fetch requests are only unsuccessful if the user runs into network issues or if there is an issue with the server. We also need to check if the HTTP response from the API was successful. This can be handled with a simple if/else statement that confirms the success of the response.
A fetch response provides an “ok” property for us to test whether an HTTP was successful or not. Here, if the response is not ok, we throw an error message. If the response is ok, we continue to turn the response object into JSON and running the rest of our code.
Now, fetch can be used for much more than just retrieving data from the server. When using fetch to relay data back to the server, like in a post request, we need to specify additional parameters. The fetch method is flexible and allows us to send in an optional second parameter to control the setting options of the request. We can handle this in three different steps for a post request.
- The first thing we need to pass in is the specific HTTP method so the server knows how to handle the request.
- Second, we need to communicate to fetch that we will be sending this data as JSON. This is done by setting the headers. We set the Content-Type to “application/json”. Then we also set the Accept request header to “application/json” which indicates the content types that the the client is able to understand.
- Third, we need to pass the actual data that we will be sending to the server which is the body. The body is made up of the data for the object that we would like to submit to the back end. In order for this to be sent correctly, we need to convert the data to a JSON string by calling JSON.stringify(). Notice in this example the body is just a variable. However, the variable is an object that we created where the values are set to data that we have collected from team creation form. So when we post the data to the back end, it will be the data that the user wanted to submit.
These three steps can all be assigned to a variable and passed in as the second parameter of our fetch request to help clean things up. The variable name is commonly set to “configObject”.
Now our data is ready to be sent to the backend!
Thanks so much for taking the time to read my post! Although, we can spend days going into the nitty gritty aspects of subjects like asynchronous code, promises and how the backend handles rendering JSON, I hope this gives a good overview of the different aspects that go into a fetch request.