DEV Community

loading...
Cover image for Using fetch with async/await

Using fetch with async/await

kishore007k profile image kishore kumar ・4 min read

The Fetch API makes it easier to make asynchronous requests and handle responses better than using an XMLHttpRequest. Fetch allows us to create a better API for simple things, using modern JavaScript features like promises.

In this post, I’m going to show the common scenarios of how to use Fetch API with async/await syntax. The goal is to make you confident on how to fetch data, handle fetch errors, cancel a fetch request, and more.

To start with the fetch async/await function you should be familiar with the async/await syntax.

Methods of calling async/await:-

In JavaScript, you can use fetch in three different ways.

  • The first way is using callbacks. When an async operation had been completed, a callback function is executed
const callbackFunction = result = {
  // Called when the operation completes
};
asyncOperation(params, callbackFunction);
Enter fullscreen mode Exit fullscreen mode
  • The second way is using the promise. The Promise is a placeholder for the async task. With the use of promises, you can handle the async operations easier.
const promise = asyncOperation(params);

promise.then(result => {
  // Called when the operation completes
});
Enter fullscreen mode Exit fullscreen mode
  • The last way is using the async/await method. It lets you write async code in a concise and sync manner.
(async function() {
  const result = await asyncOperation(params);
  // Called when the operation completes
})();
Enter fullscreen mode Exit fullscreen mode

The Fetch API accesses resources across the network.
You can make HTTP requests (GET, POST), download, and upload files.

To start a request, call the special function fetch()

const response = await fetch(resource[, options]);
Enter fullscreen mode Exit fullscreen mode

The fetch() accepts two arguments

  • Resource
  • Options

The Resource can be a request object or a URL string.

Options is a configuration object with properties like methods (GET, POST), headers, body, and more

Executing fetch() starts a request and returns a promise. When the request completes, the promise is resolved with the Response. If the request fails due to some network problems, the promise is rejected.

Here is an example:

async function fetchMovies() {
  const response = await fetch('/movies');
  // waits until the request completes...
  console.log(response);
}
Enter fullscreen mode Exit fullscreen mode

fetchMovies() is an asynchronous function since it’s marked with the async keyword.

await fetch('/movies') starts an HTTP request to '/movies' URL. Because the await keyword is present, the asynchronous function is paused until the request completes.

When the request completes, the response is assigned with the response object of the request. Let’s see in the next section how to extract useful data, like JSON or plain text, from the response.

Fetching JSON:-

The Response object returned by the fetch() is a generic placeholder for multiple data formats.

Here’s how you could fetch movies as JSON data from the response object:

async function fetchMoviesJSON() {
  const response = await fetch('/movies');
  const movies = await response.json();
  return movies;
}

fetchMoviesJSON().then(movies => {
  movies; // fetched movies
});
Enter fullscreen mode Exit fullscreen mode

response.json() is a method on the Response object that lets you extract a JSON object from the response. The method returns a promise, so you have to await for the JSON: await response.json().

The response object offers a lot of useful methods (all returning promises):

  • response.json() returns a promise resolved to a JSON object
  • response.text() returns a promise resolved to raw text
  • response.formData() returns a promise resolved to FormData
  • response.blob() returns a promise resolved to a Blog (a file-like object of raw data)
  • response.arrayBuffer() returns a promise resolved to an ArryBuffer (raw generic binary data)

Handling fetch errors:-

When I was familiarizing with fetch(), I was surprised that fetch() doesn’t throw an error when the server returns a bad HTTP status, e.g. 404 or 502.

Let’s try to access a non-existing page '/oops' on the server. As expected, such request ends in a 404 response status:

async function fetchMovies404() {
  const response = await fetch('/oops');

  response.ok;     // => false
  response.status; // => 404

  const text = await response.text();
  return text;
}

fetchMovies404().then(text => {
  text; // => 'Page not found'
});
Enter fullscreen mode Exit fullscreen mode

When fetching the URL '/oops' the server responds with status 404 and text 'Page not found'. Surprisingly, fetch() doesn’t throw an error for a missing URL, but considers this as a completed HTTP request.

fetch() rejects only if a request cannot be made or a response cannot be retrieved. It might happen because of network problems:
no internet connection, host not found, the server is not responding.

Fortunately, response.ok property lets you separate good from bad HTTP response statuses. The property is set to true only if the response has status from 200 to 299, inclusive.

In the above example, the response.ok property is false because the response has status 404.

If you’d like to throw an error on a bad HTTP status (outside of the range 200-299), check the value of response.ok property and throw an error manually

async function fetchMoviesBadStatus() {
  const response = await fetch('/oops');

  if (!response.ok) {
    const message = `An error has occured: ${response.status}`;
    throw new Error(message);
  }

  const movies = await response.json();
  return movies;
}

fetchMoviesBadStatus().catch(error => {
  error.message; // 'An error has occurred: 404'
});
Enter fullscreen mode Exit fullscreen mode

Some other Blogs I have published:-

Feel free to explore my GitHub Profile:-

GitHub

Discussion (3)

pic
Editor guide
Collapse
123aswin123 profile image
Aswin Vayiravan

Great article Kishore,

You could have also wrap the async call in a try / catch block for the error handling, any specific reason as to why that approach wasn't chosen in the last snippet?

Collapse
kishore007k profile image
kishore kumar Author

Thanks, Aswin. Yeah, that is a good suggestion. Maybe I might add it in the next one in detail.