HTTP Requests in StencilJS with the Fetch API

HTTP Requests in StencilJS with the Fetch API

Follow Josh Morony on

When building applications with Ionic, we will often need to fetch some data over the network - whether that is locally to pull in data from a JSON file, or through the Internet to load data supplied by some API.

If you’ve been around for a while you might recall using an XMLHttpRequest() to perform HTTP requests with JavaScript - this wasn’t/isn’t a particularly nice way to perform requests, and many people would use additional libraries to help simplify the process of sending HTTP requests.

Browser APIs have come a long way over the years, and now we have the Fetch API that is built in to modern browsers by default available to us. This API makes it much simpler to execute HTTP requests without the use of an external library. It performs a similar role to the standard XMLHttpRequest, but it uses Promises and is much simpler to use. A simple request using the Fetch API might look something like this:

let response = await fetch("https://someapi.com/data");
let json = await response.json();

We can run the code above in our Ionic applications with no need to install any 3rd party libraries. In this tutorial, we are going to walk through the basics of using the Fetch API.

This tutorial has an intended audience of Ionic/StencilJS developers, since using the Fetch API could be considered the default method for running HTTP requests in that context. If you are using Ionic/Angular, for example, you would be more likely to use Angular’s HttpClient. However, the Fetch API is just a generic browser API that can be used anywhere.

NOTE: If you are interested in using Redux in your Ionic/StencilJS applications, I already have a much more advanced tutorial for loading data with the Fetch API and Redux here: State Management with Redux in Ionic & StencilJS: Loading Data.

GET Requests

We are going to discuss some basic examples of using the Fetch API. Keep in mind that we are just going to display the basic request here, but error handling is also an important topic that we will cover in the last section of this tutorial.

To execute a GET request with the Fetch API, we would do the following:

let response = await fetch("https://someapi.com/data");
let json = await response.json();

We supply the URL that we want to fetch the data from to the fetch method. This will return a Promise with the result, so we await it (if you prefer, you could also use the standard Promise syntax with .then()). Once the Promise resolves, we can then access the data returned through the json() method.

POST Requests

Running GET requests are usually a bit easier than POST requests, because we typically need to send a bit of extra information with a POST request. We need to send the data itself, as well as any additional headers that might need to be set.

This example is a little bit more complex, but still quite manageable:

let data = {
    comment: 'hello',
    author: 'josh'
};

let response = await fetch("https://someapi.com/comments", {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
        'Content-Type': 'application/json'
    }
});

let json = await response.json();

We have defined some data that we want to send along to someapi.com. Now instead of just supplying the URL to fetch, we supply an Object as a second parameter. This object contains all of the extra information we need.

We use this object to set the method to POST, we add the data we want to send to body as a JSON string, and then we set the appropriate Content-Type header (which is usually going to be application/json). Aside from that, the rest is the same. We just await the fetch and the json() method.

Handling Errors

One perhaps awkward aspect of the Fetch API is that it will not cause a Promise to reject in the case of an HTTP error. This means that even if there is some kind of server error like a 500 - Internal Server Error the request will still be considered to have executed successfully. A request was made to the server, and a response was received back from the server - technically, you could consider that a “success” even if the response was an error.

That means that if we were simply to wrap our code in a try/catch block (as we might usually do to handle errors), it won’t trigger the catch block under all circumstances:

try {
  let response = await fetch("https://someapi.com/data");
  let json = await response.json();
} catch(err) {
  console.log(err);
}

What will happen is that we will receive the response back successfully through the resolved Promise, but the ok status will be false if a server error occurred. In the context of our application, we would probably consider a server error to be undesirable behaviour and we would want to trigger some kind of error handling. To handle this situation, we will just need to add a little more logic to our request:

try {
    let response = await fetch("https://someapi.com/data");
    if(!response.ok){
        throw new Error(response.statusText);
    }
    let json = await response.json();
} catch (err) {
    console.log(err);
}

Now we check the response for the ok status, and if it is not true we throw an error. Since this is inside of the try block, if we throw an error it will cause it to fail and trigger the catch, which will result in the error being logged out in this case.

Rather than manually writing this code for every request, you might prefer to set up a little helper function to help handle errors, e.g:

try {
    let response = await fetch("https://someapi.com/data");
    handleErrors(response);
    let json = await response.json();
} catch (err) {
    console.log(err);
}

In this case, we can just pass the response to a handleErrors method that we have defined, and then throw an error in that method if necessary.

Summary

There are many approaches we can take to performing HTTP requests in our Ionic applications, and using an additional library to handle those requests is absolutely fine. In the case of Ionic/Angular, it even makes more sense to use the default HttpClient that is included since. However, it is nice that we now have a default browser API that is simple enough to use out of the box to perform HTTP requests without requiring any additional libraries.

If you are building Ionic/StencilJS applications, then you might also be interested in combining this concept of using the Fetch API with a service to handle performing those requests for you. If you are interested in a more advanced data loading implementation with Redux, remember to check out State Management with Redux in Ionic & StencilJS: Loading Data.

Check out my latest videos: