The Only Parts of Fetch API in JavaScript That Will Get You Far In Your Career
Tags: javascript, webdev, programming, node
Published: 2022-03-06 18:22:12

The `fetch` api in JavaScript provides developers an interface to work with HTTP requests and the HTTP pipeline. It is also used to process responses received from those requests. Sending requests with the fetch api is working with asynchronous code using the global `Promise` object in JavaScript to deliver flexibly.

It is the successor to `XMLHttpRequest` which is a better (and modern) alternative to communicate with resources remotely across the network. It can perform all of the tasks that `XMLHttpRequest` was capable with.

I am a lead engineer and I spent 100% of my time on JavaScript. It is my only language I am comfortable with. I also spent too much time trying to master `fetch` in all of its ins and outs because in the real world you most likely won't be needing to use things like `TextDecoder` or any of that extra stuff to work with HTTP requests/responses. There is a good reason behind this: The _weird_ parts are already done for you in libraries available publicly.

So what I learned over time when working on projects in general is that striving for perfection is not the solution to achieve success. There is no perfect solution. But a good way to get very far in life is to _work smart_.

In this post we will go over the parts of the `fetch` api that is _just enough_ to get you very far in your development career. This means that you will _rarely_ be using methods from the `fetch` api outside of this tutorial. In other words, the information in this article is just enough to get you to focus on other parts of your JavaScript development career. You _don't need to understand everything about fetch_ in order to succeed. You just need the understand the _parts you will be asked to do in your projects_.

A chief officer in my company (who is specialized in a skill outside of I.T.) recently applauded for an employee member in another department that quickly spun up a website which performs _very fast_. That employee used wordpress. He _worked smart_.

## Sending Requests and Receiving Responses

You should be familiar with the `Request` and `Response` object that the `fetch` object communicates with. When you work with these two objects you are actually hitting a lot of birds with one stone, because as you venture out in the real world you will notice that these two objects are either mimiced or reused in frameworks like `Gatsby` functions, the development server in `webpack`, native libraries in Node.js use this interface as well in their `http` module.

The properties/methods are also _purposely_ used as a convention to work with responses in libraries like [got](https://github.com/sindresorhus/got), so by knowing `Request` and `Response` you will have sort of a "shortcut" in the learning process of open sourced tools.

The most common method you will be using from `fetch` is the `get` method.

The example below is making a `get` request to fetch a list of `hound` dog breeds:

```js
window.addEventListener('load', async (event) => {
  const url = `https://dog.ceo/api/breed/hound/list`

  const response = await fetch(url)
  const result = await response.json()

  console.log(result)
})
```

Result:

```json
{
  "message": [
    "afghan",
    "basset",
    "blood",
    "english",
    "ibizan",
    "plott",
    "walker"
  ],
  "status": "success"
}
```

The resource becomes available as a `Response` object after the request completes.

This `Response` object contains your data which is the most sensitive part, so it needs to be taken care of like it is your baby. `fetch` also provides different methods for working with the `Response`. It is the wrapper for the fetched resource that comes with useful properties and methods to inspect it.

The way we obtain the data depends on the methods we use and majority of the time it also depends on the _type_ of the contents. We would resolve the response's contents using the JavaScript `Promise` API which helps us parse the contents into the final format we expect.

For example, when the response is returned and we want to obtain the data in the _raw text format_, the `Response` provides the `.text()` method to read the fetched resource's contents:

```js
const result = await response.text()
// Result: "{"message":["afghan","basset","blood","english","ibizan","plott","walker"],"status":"success"}"
```

In this example we used the `text` method and it was successfully resolved to us. This is fine but when we look at the contents it's actually a JSON string.

Since the data is already a JSON string, we can just use the `json` method to automatically parse the string into a javascript object for us (otherwise we would have to parse it ourselves every time by using `JSON.parse`):

```js
const response = await fetch(url)
const result = await response.json()
```

_Most_ of the time especially in modern web development we'll mostly be using the `.json()` method to read data. But it's worth mentioning that we should be aware of when _not_ to use it, or else we would end up with something like this:

```js
const response = await fetch(url)
const result = await response.json()

console.log(result)
```

![fetch-in-javascript-json-method-error.png](https://jsmanifest.s3.us-west-1.amazonaws.com/posts/the-only-parts-of-fetch-in-javascript-that-will-get-you-very-far-in-your-career/fetch-in-javascript-json-method-error.png)

This is a catastrophic error because it typically stops our application from behaving the way we expect it to afterwards.

There are other ways we can read the response data (which all comes in as a `Promise`) such as:

1. `response.blob()`
2. `response.formData()`
3. `response.arrayBuffer()`

## Response Status Codes

The `Response` object also comes with three properties we can use to inspect if the request succeeded or not:

```js
const response = await fetch(url)

console.log(response.status) // 200
console.log(response.statusText) // "OK"
console.log(response.ok) // true
```

The most important property here is the `.status` property. It returns an HTTP status code which identifies the status of the request's response which we can use to handle the upcoming steps for our app accordingly.

The most common (and necessary) status codes we should know is `404` and `500` (and `200` for success) due to its frequent occurrences on the web.

When responses return with a `404` status code it usually means one of:

1. The requested resource could not be found
2. The URL is not recognized
3. The endpoint is recognized but the resource is gone or missing
4. The request resource is protected from unauthorized users from viewing it

When responses return with a status code of something above `500` it is an error from the server itself. I commonly see `500` as opposed to its related codes like `503` which means that the server could not handle the error it received so the response was returned empty instead.

## Fetch Use Cases

We can use the `fetch` in JavaScript browser environments to retrieve data (as shown previously), but we can also use it as a way to modify or add resources to a location.

For example, we can use it to process data after selecting to upload files in the DOM:

```html
<form name="upload-form" method="post">
  <label for="upload-files">Click to upload one or more files</label>
  <input
    name="upload-files"
    type="file"
    placeholder="Select file(s)"
    multiple
  /><input />
</form>
```

With this we can use `fetch` in our `form` submit handlers to upload files for our users:

```js
async function onSubmit(event) {
  event.preventDefault()
  const fileInput = [...event.target.elements].find((el) => el.type === 'file')
  const filesList = fileInput.files
  const file = filesList[0]

  await fetch(`/upload-my-data?filename=${file.name}`, {
    body: file,
    method: 'post',
  })
}

document
  .querySelector(`form[name="upload-form"]`)
  .addEventListener('submit', onSubmit)
```

We can also use it to upload data in JSON format to create plain object resources on a remote location:

```html
<form name="new-profile-form" method="post">
	<div>
		<input type="text" name="name" placeholder="Your Name"></input>
	</div>
	<div>
		<input type="text" name="email" placeholder="Your Email"></input>
	</div>
	<div>
		<textarea name="message" placeholder="Message" ></textarea>
	</div>
	<button type="submit">Submit</button>
</form>
```

```js
async function onSubmit(event) {
  event.preventDefault()
  const body = {}
  const formElements = [...this.elements].filter((el) =>
    el.hasAttribute('name'),
  )

  for (const el of formElements) {
    body[el.getAttribute('name')] = el.value
  }

  const response = await fetch(`/upload-my-data`, {
    body: JSON.stringify(body),
    method: 'post',
  })

  console.log(`[onSubmit] data`, await response.json())
}

document
  .querySelector(`form[name="new-profile-form"]`)
  .addEventListener('submit', onSubmit)
```

![fetch-post-json-data-javascript.png](https://jsmanifest.s3.us-west-1.amazonaws.com/posts/the-only-parts-of-fetch-in-javascript-that-will-get-you-very-far-in-your-career/fetch-post-json-data-javascript.png)

## Conclusion

These are the the base features you really need to get very far in your web development career. _If_ there comes a time when asked to do something out of your scope that `fetch` is capable of doing, then _all you have to do is google it_.

And that concludes the end of this post! I found you found this to be valuable and look out for more in the future!

Find me on [medium](https://medium.com/@jsmanifest)