HTTP Polling – the Good, the Bad and the Ugly

Explore three approaches to implementing short HTTP polling using client-side JavaScript. This article covers a basic method with callbacks, a more modern approach using async/await, and a streamlined solution with RxJS for handling complex asynchronous logic. Discover the strengths and considerations of each technique to choose the best fit for your project.


This content originally appeared on HackerNoon and was authored by pyotruk

\ In this article, I'll cover three approaches to implementing short HTTP polling, using client-side JavaScript (TypeScript). Short polling involves making repeated, separate requests to check the status of a resource.

\ Imagine we have an API with two endpoints: postTask and getTask. After posting a task (using the postTask endpoint), we need to continuously poll the getTask endpoint until it returns a status of either DONE or FAILED.

We'll start by exploring the Ugly approach.

The Ugly

The first thing that comes into mind is a recursive setTimeout:

function handlePolling(
  taskId: string,
  done: (result: string) => void,
  failed: (err: string) => void,
): void {
  API.getTask(taskId).then(response => {
    switch (response.status) {
      case 'IN_PROGRESS':
        setTimeout(() => handlePolling(taskId, done, failed), 1000);
        break;
      case 'DONE':
        return done(response.result);
      case 'FAILED':
        return failed('polling failed');
      default:
        return failed(`unexpected status = ${response.status}`);
    }
  }).catch(err => {
    failed(`getTask failed - ${err}`);
  });
}

\ This approach is quite straightforward but comes with a couple of notable flaws:

\

  • Callbacks: done & failed.

    While this is largely a matter of preference, using callbacks can start to resemble the infamous "callback hell" from early Node.js days. If we tried to return a Promise, we'd encounter a branching structure since each Promise could either resolve or reject. As a result, we're forced to stick with callbacks for simplicity.

  • Recursion

    The bigger issue is that recursion can make debugging more difficult. Each recursive call adds complexity, making it harder to track the flow and pinpoint where things go wrong.

The (Not-So) Bad

Let’s rewrite it in a more linear fashion with async & await:

const sleep = (timeout: number) => new Promise((resolve) => setTimeout(resolve, timeout));

async function handlePolling(taskId: string): Promise<string> {
  while (true) {
    try {
      await sleep(1000);
      response = await API.getTask(taskId);

      switch (response.status) {
        case 'IN_PROGRESS':
          continue;
        case 'DONE':
          return response.result;
        case 'FAILED':
          return Promise.reject('polling failed');
        default:
          return Promise.reject(`unexpected status = ${response.status}`);
      }
    } catch (err) {
      return Promise.reject(`getTask failed - ${err}`);
    }
  }
}

\ This approach is much cleaner. We've encapsulated setTimeout within a sleep function, and we now return a Promise that can be awaited. The code is more readable and easier to maintain.

\ The only detail that stands out is the while(true) loop. This can be improved by using while(status === 'IN_PROGRESS'), which makes the intent clearer. Additionally, it's a good idea to implement a safety mechanism to limit the number of getTask requests. This helps protect against the rare case where the API might get stuck in an infinite loop or experience an unexpected delay.

The Good

The approach I prefer the most is using RxJS — a library specifically designed for handling event streams. You can think of it as “lodash for Promises.” RxJS provides a powerful and flexible way to manage asynchronous events like HTTP polling, making it easier to handle complex workflows in a more declarative manner, e.g.:

\

function handlePolling(taskId: string) {
  return new Promise<string>((resolve, reject) => {
    interval(1000).pipe(
      switchMap(() => API.getTask(taskId)), // runs the request each time the interval emits
      takeWhile(response => response.status === 'IN_PROGRESS', true),
      filter(response => response.status !== 'IN_PROGRESS'),
    ).subscribe({
      next: response => {
        switch (response.status) {
          case 'DONE':
            return response.result;
          case 'FAILED':
            return Promise.reject('polling failed');
          default:
            return Promise.reject(`unexpected status = ${response.status}`);
        }
      },
      error: err => reject(`getTask failed - ${err}`),
    });
}

\ What I love about RxJS is how straightforward it makes the code. With the takeWhile operator, we clearly define when to stop the loop, and by using the filter operator, we can skip handling any responses where the status is still IN_PROGRESS. This creates a clean, declarative flow that's easy to read and maintain.

Conclusion

Both the "Good" and the "Not-So-Bad" approaches are viable ways to handle HTTP polling. However, if your project involves a significant amount of asynchronous logic — such as polling, interdependent async tasks, background loading or complex calculations — then it’s worth considering adopting RxJS. Its powerful tools for managing streams of asynchronous events can greatly simplify your code and make it more maintainable in the long run.


This content originally appeared on HackerNoon and was authored by pyotruk


Print Share Comment Cite Upload Translate Updates
APA

pyotruk | Sciencx (2024-09-17T08:11:52+00:00) HTTP Polling – the Good, the Bad and the Ugly. Retrieved from https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/

MLA
" » HTTP Polling – the Good, the Bad and the Ugly." pyotruk | Sciencx - Tuesday September 17, 2024, https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/
HARVARD
pyotruk | Sciencx Tuesday September 17, 2024 » HTTP Polling – the Good, the Bad and the Ugly., viewed ,<https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/>
VANCOUVER
pyotruk | Sciencx - » HTTP Polling – the Good, the Bad and the Ugly. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/
CHICAGO
" » HTTP Polling – the Good, the Bad and the Ugly." pyotruk | Sciencx - Accessed . https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/
IEEE
" » HTTP Polling – the Good, the Bad and the Ugly." pyotruk | Sciencx [Online]. Available: https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/. [Accessed: ]
rf:citation
» HTTP Polling – the Good, the Bad and the Ugly | pyotruk | Sciencx | https://www.scien.cx/2024/09/17/http-polling-the-good-the-bad-and-the-ugly/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.