Custom Loading Animation on Fetch Call in Vanilla Javascript / CSS / HTML 5
Tags: javascript, beginners, html, animatedsvg
Published: 2022-02-07 14:01:34

Do you have an API call that is sorta slow, and you want to keep your user occupied while it loads and you're not quite sure how to do it?  Well, it's easier than you'd think!  

## Why a custom loading animation for vanilla javascript? Meh...why not?
This blog post comes out of the project that I co-created for the first phase of the Flatiron School Software Engineer Program.  We built a game that called the Met Museum API, which was really neat! Unfortunately, it had to make 4-7 API calls per game-round to make sure it got enough clean data.  Eventually it all worked, but it took as much as 5-seconds for the API calls to return and the Dom to update.  


![An image of loading times from API calls, each time is approximately 1 second](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16pmangb3igahrl0wfa1.png)

Seeing those gross loading times puts us in a good place to explore where to go next. 

## User Experience
The biggest UX issue we have is that when you finish a round the game appears to be frozen while it's waiting for the new data to load.  

>UX is more than just making things pretty - it's about making the experience more responsive to the user's needs

Even though the final version of the game implements a few modal windows to occupy the user, we wanted to really cover the loading time with some branded loading animation.  As it turned out it was pretty straight forward to hook a loading animation into the asynchronous fetch call.  

Now, let's be straight: there's lots of ways to implement a loading spinner - this way is fine for small special applications.  Is it what I'd use in any kind of larger deployment, even a vanilla javascript one?  No, no I probably wouldn't  But, this is a cool little trick to get things going in a single page application.

### What are we doing for a loading animation?
Our loading animation is pretty simple, we're going to embed an animated SVG in a hidden div, and when we call it with Javascript it goes from hidden to visible.  Pretty easy - let's see how it's done!

## Animated SVG in a Hidden Div
^Sounds like the title of a Russian fairy tale.  
So, how about that animated SVG I keep talking about, what's that all about?  Let's see:
SVG stands for Scalable Vector Graphics, and it's basically an inbuilt vector rendering engine that is XML based.  So, what it takes to get it going is the same as everything else around here, a bit of code.

Try this one below, it comes from [Mozilla MDN] (https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateMotion) and is a lovely example.
```html
<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
  <path fill="none" stroke="lightgrey" d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
  <circle r="5" fill="red">
   <animateMotion dur="10s" repeatCount="indefinite" path="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
  </circle>
</svg>
```
What the heck, let's use that as part of our example.  Put that svg into a `Div` at the bottom of your body section, set it to `display:none` and then set a few more options to get the background to cover the page.  And the easy way to do it is to simply change the `display: none` to a `display: block` (or whatever you need) when the right moment occurs in your script.  

See it in action on repl.it here:
{% replit @hariseldon27/Vanilla-JS-Spinner-in-Hidden-Div %}

## Hooking it to the Fetch Request

Yeah yeah yeah - okay we get it - it's easy as pie to make a hidden div appear.  And yeah, we get it - maybe it isn't the cleanest way to do it, but if when push comes to shove and you can only have one file it's a worthwhile tool to have around.

So how do we go about hooking the appearance of our cool new loading animation that we ~~stole~~ borrowed from MDN?  Well, it's pretty easy actually.  But, it's worth talking a little about about how to ensure you are making an asynchronous fetch request first.

## Async Await / Fetch - a toast to the happy couple
![animated gif of two champagne glasses clinking in a toast](https://media.giphy.com/media/29wik0hT7Ck9jppi6D/giphy.gif)

In order to improve the user experience of sites that rely on calls to servers or APIs for information, Javascript gives us a neat way to manage what code is running when. 

Under normal circumstances our code runs in more or less a linear fashion in Javascript - aside from neat features like function hoisting and scope.  However, we can ask Javascript to treat a function asynchronously from the other code that it's being asked to execute.  This also means we can ask other functions to await that asynchronous code to finish before it tries to complete its task.  We will make use of this in our fetch call, especially with our loader in mind.

To move your fetch function into the asynchronous pile put `async` before the function declaration like so:

```javascript
 async function goFetch(data) {
   fetch("apiurl.com/endpoint")
   .then((resp) => resp.json())
   .then((data) => doSomething(data))
}
```

Then in our callback function we can simply remind it that it needs to `await` that fetch to complete before it tries to run.
```javascript
await function doSomething(data) {
    console.log(data)
}
```

So where do we hook in the loading animation?  Well, we've already got our fancy-schmancy show/hide functions in JS if you remember.  

```javascript
const loadingDiv = document.getElementById("loading");
loadingDiv.addEventListener('click', hideSpinner)

function showSpinner() {
  loadingDiv.style.display = 'block';
}

function hideSpinner() {
  loadingDiv.style.display = 'none';
}
```
Those `showSpinner()` and `hideSpinner()` functions can just go at the points where it makes sense: **show it right after the fetch, and hide it right after we finish populating the dom with data.**  

In our Met Guess game we fire the `showSpinner()` function right after our very first fetch request, and we don't run the `hideSpinner()` function until after the API returns data.  What could we have done better?  Well, look at the console logs and see if you can guess!  If you said, have the spinner appear immediately and then stay up until the DOM render completed, you're right...always room for improvement around here!

See that cool codepen here:
{% codepen https://codepen.io/HariSeldon27/pen/PoOwwjp %}

## Conclusion
In this post we've talked about why we might want to use a loading animation, we looked at one sorta janky way to implement it, and more importantly we looked at a way to hook your loading animation into the fetch call of your Javascript.  

Have questions?  Me too!  Let's talk. 
 
I respond to any and all responses!