Queuing Rest Apis using JavaScript
Tags: javascript, programming, webdev, discuss
Published: 2023-04-10 16:46:24

Many of us web developers, frontend developers, fullstack developers have been using REST apis for ages. I am also one of these developers who constantly uses rest apis for my web apps. But whenever I used them, I would often wish that the library I choose would have an inbuilt Queue in them to handle requests, keep them stored in case of a network issue or something else, resume the handling of the request once the internet is running again all while handling 1 request at a time to avoid any inconsistencies with data. 

Just to make things clear, I am not the most perfect developer so I do make mistakes quite often. That is where I would need you guys' help. I have come up with a small wrapper Class and function around the http library that I often use (axios) to implement a queuing system. It is not the best solution yet, but with some changes and good optimization it could be.

{% gist https://gist.github.com/SoorajSNBlaze333/e6cd7d3103272af7298b4414cd19b024 %}

As you can see above, I have made things fairly simple by creating an `API` class that handles the request in a generic format and then I have created a function called `queuedAPI` that will expose the api methods of the `API` Class and queue them into the queue. Once it is added to queue, the requests are dequeued in the order in which they were added to the queue. I am also making sure to see if the client has a navigator object and if we are connected to internet before dequeuing the promise. If we are not connected to the internet, we will keep looking until the browser gets a connection to the internet. I know this is performance intensive, but I am trying to write an observer or find different ways to limit the number of retries. One way could be to use a limit variable like `RETRY_LIMIT = 5` or something like that.

Another idea that I have is to store the queue in the local storage of the browser. This is because if the internet is lost and the user refreshes the page, then the queue would become empty. If I were to store the queue in the local storage then I would be able to access it on the page load and dequeue the existing queue requests that was done before the page refresh. But that would also mean that I would have to find a way to not store any sensitive information that would be passed in the api such as password info or payment info. So I would have to avoid those apis and provide an option in the api if the developer would like that api to be stored in a temp storage or not.

Lastly I would like to add a priority to each queue item, so that the queue is dequeued with priority in mind. 

`App.jsx`
```javascript
import { useEffect, useState } from "react";
import Button from "./components/Button";
import api from "./libs/api";

const App = () => {
  const [counter, setCounter] = useState(0);
  const [apiData, setApiData] = useState(null);
  const [online, setOnline] = useState(navigator.onLine??false);

  const handleClick = (method = 'get') => {
    setCounter(api.currentQueue.length + 1);
    let request = api.get;
    if (method === 'post') request = api.post;

    return request('https://62baf8ff573ca8f8328ff37d.mockapi.io/api/v1/users')
      .then((data) => setApiData(JSON.stringify(data)))
      .then(() => setCounter(prev => prev - 1))
      .catch((error) => console.log(error));
  }

  useEffect(() => {
    setInterval(() => {
      setOnline(navigator.onLine??false);
    }, 2000);
  }, []);

  const renderNetworkStatus = () => {
    if (online) {
      return <div className="flex justify-center items-center border-2 border-green-500 bg-green-50 rounded-full px-2">
        <div className="h-2 w-2 bg-green-500 rounded-full mr-1" />
        <div className="text-green-500 text-xs font-semibold mb-[0.5px]">online</div>
      </div>
    }
    return <div className="flex justify-center items-center border-2 border-red-500 bg-red-50 rounded-full px-2">
      <div className="h-2 w-2 bg-red-400 rounded-full mr-1" />
      <div className="text-red-500 text-xs font-semibold mb-[0.5px]">offline</div>
    </div>
  }

  return (
    <div className="h-full w-full flex justify-center items-center flex-col">
      <div className="text-3xl my-2">Requests Left in Queue: {counter}</div>
      <section className="flex justify-center align-center gap-2">
        <Button onClick={() => handleClick('get')}>Make get request</Button>
        <Button onClick={() => handleClick('post')}>Make post request</Button>
      </section>
      <div className="text-xs overflow-y-auto max-h-[400px] p-4">{apiData}</div>
      <div className="absolute bottom-3">{renderNetworkStatus()}</div>
    </div>
  );
}

export default App;
```

{% youtube xxYzric89bo %}

I'm also adding a small video clip of the queue when we request apis but not connected to the internet and then how the apis execute in order when we are connected again.

If you guys feel that there is any kind of optimization or refactoring that can be made to make this even better or faster, please let me know in the comments. 

And if you do like this idea please star this gist that contains the code for the queue API
[https://gist.github.com/SoorajSNBlaze333/e6cd7d3103272af7298b4414cd19b024](https://gist.github.com/SoorajSNBlaze333/e6cd7d3103272af7298b4414cd19b024)