JavaScript Fetch API is the modern standard for creating network Requests inside browsers. Have you ever written confusing xmlhttprequest code with nested callback routines? Then i’m sure you were aware of why the programming community cheered when fetch finally came around. Fetch isn’t just replacing the older Way; it changes entirely how we think about http Requests. It uses promises and integrates perfectly with current web capabilities such as service workers and CORS.
Think of fetching like ordering takeout at a drive-through restaurant. You roll up to speak to someone at the microphone and ask for what you’d like. They hand you a receipt which isn’t your food yet. It is a promise of food. You could sit and wait for your food or continue driving and address your food when it gets there. Fetch is similar. You call fetch() with a URL and it gives you back a promise. At that point your program continues executing while the network does its job.
Now that we’ve got our minds wrapped around that concept, let’s go through 5 key ideas that will allow you to stop copying fetch examples out of stackoverflow and truly understand what is going on underneath.
Creating your first request using fetch api with javascript
The easiest fetch request is really pretty straightforward. Pass a URL to the fetch() function that exists globally throughout both window and worker contexts. The function returns a promise right away. After the promise is resolved, you’re given a Response object which represents the server’s reply.
However, this is only half of the battle. The Response object represents http status code(s), Headers(s), and raw body stream(s). By default it doesn’t give you your actual data. You have to specifically tell fetch() what format of data you’d like your data returned as by calling something like .JSON(), .text(), or .blob(). Oh yeah – those methods are asynchronous as well. They return promises too!
So basically, a typical fetch call now requires either two “await” statements or two “.then()” blocks: One to get the Response object and another to get the actual body data out of that object! It looks something like this:
Const Response = await fetch('https://api.example.com/users');
Const data = await Response.JSON(); Most likely skipping that second step is probably going to be your #1 most common fetch bug ever.
Handling Errors correctly using JavaScript Fetch API
This is what sets apart people who casually mess around with fetch versus professionals. And honestly – it’s just flat-out hard to wrap your brain around until somebody explains it clearly to you.
Fetch does not reject the promise when server responds with http error statuses (ie 404 or 500), let that sink in for a minute, if you try requesting a URL that doesn’t exist – that promise still resolves successfully. So any catch blocks associated with your promise will not trigger. This is not a bug, this is a deliberate design decision by fetch’s authors. The authors of fetch are simply stating that fetch only rejects promises when there is an issue preventing completion of the request at all (i.e. Things like DNS lookup issues / connection timeout issues / user being offline).
Therefore you have to manually determine whether the request actually succeeded! The Response object has a nice boolean property called “ok”. It returns true for anything between 200 & 299… False for everything else. If “ok” is false, you should throw an error yourself or handle the failure as needed.
There is no Way around it, the most reliable pattern combines try.catch blocks with an explicit check on Response.ok! Try/catch blocks will catch network level Errors such as being offline… Response.ok checks will catch http level Errors such as 404.
Together they offer complete coverage of Errors! If you skip checking Response.ok, your application will happily try to parse an error page as JSON… Then fail in some other part of your application codebase entirely.
Sending Data w/ POST & configuring Headers
Fetch isn’t just for retrieving data – it can also send data! And that is where configuring Headers becomes important! The second argument passed to fetch() is an object which allows you configure almost every single thing about the request!
The most common settings are method properties & header properties! To send JSON data to a server you need to set the method to POST & add a content type header telling the server what kind of data you are sending! Plus you need to provide a body property which contains the actual data which must be stringified if you’re sending JSON!
Configuring Headers can be done via either providing an oject in the config option or using the header constructor for more complex setups! Providing Headers via object allows you more flexibility for easier implementations whereas using the header constructor provides more power & ability for more advanced configurations!
Either Way both approaches work!
Canceling Requests w/ AbortController
Not all Requests need to finish! Occasionally users leave pages before data finishes loading… Occasionally they start typing letters in a searchbox rendering their previous search request obsolete… Without cancellation those abandoned Requests keep running… Eating bandwidth & possibly updating your UI with stale data after users have already moved on to something else!
AbortController api solves this issue nicely! Create an AbortController… Pass its signal to ffetch options… Call .abort() whenever you want to cancel a request! Ffetch monitors the signal… And when canceled it rejects the promise with specific AbortError when canceled.
Here’s the simplest Way to cancel using AbortController:
Const controller = new AbortController();
Fetch('/api/data', {signal: controller.signal});
controller.abort(); When you call .abort(), the fetch promise rejects w/ an error whose name property is equal to ‘AbortError.’ Therefore you can check for this type of error inside catch blocks & determine whether users cancelled intentionally or the request failed.
Additionally since abortcontrollers are single-use, once you call .abort() on them, they can’t be used again for another request! If you need to retry a failed request – create a new controller!
Conclusion
Once you grasp how to mentally model it, the JavaScript Fetch API isn’t overly complex. It’s a promise based interface returning a Response object, from which you need to actively extract (convert) your desired data. By now we’ve gone over the basics of initiating GET/POST requests, error handling via proper use of response.ok and sending POST requests along with customized header information. Additionally, we’ve reviewed aborting/cancelling in flight requests utilizing AbortController as well as retrieving response body content in multiple formats.
If you internalize the 5 core concepts above, they’ll help cut down your time spent debugging and improve the quality and cleanliness of your networking code. To further explore all of the features and options of the full Fetch API spec please refer to the MDN Documentation covering Using The Fetch API. In addition to this documentation, for an example of using the fetch api in various applications/javascript development environments, see the JavaScript.info tutorial on the fetch API. This tutorial contains many interactive exercises and provides great detail on common usage scenarios.
New to HTML? Start Here: HTML Tutorial for Beginners: Your Complete Introduction to HTML Basics
New to CSS? Start Here: CSS Introduction: Master 5 Core Concepts Easily
New to JavaScript? JavaScript Introduction: 5 Proven Steps to Learn JS
[INSERT_ELEMENTOR id=”122″]

