Using setInterval() to do simplistic continuous polling

JavascriptAjaxSetintervalPolling

Javascript Problem Overview


For a simple web app that needs to refresh parts of data presented to the user in set intervals, are there any downsides to just using setInterval() to get a JSON from an endpoint instead of using a proper polling framework?

For the sake of an example, let's say I'm refreshing the status of a processing job every 5 seconds.

Javascript Solutions


Solution 1 - Javascript

From my comment:

I would use setTimeout [docs] and always call it when the previous response was received. This way you avoid possible congestion or function stacking or whatever you want to call it, in case a request/response takes longer than your interval.

So something like this:

function refresh() {
    // make Ajax call here, inside the callback call:
    setTimeout(refresh, 5000);
    // ...
}

// initial call, or just call refresh directly
setTimeout(refresh, 5000);

Solution 2 - Javascript

A simple non-blocking poll function can be implemented in recent browsers using Promises:

var sleep = duration => new Promise(resolve => setTimeout(resolve, duration))
var poll = (promiseFn, duration) => promiseFn().then(
             sleep(duration).then(() => poll(promiseFn, duration)))

// Greet the World every second
poll(() => new Promise(() => console.log('Hello World!')), 1000)

Solution 3 - Javascript

You can do just like this:

var i = 0, loop_length = 50, loop_speed = 100;

function loop(){
	i+= 1; 
	/* Here is your code. Balabala...*/
	if (i===loop_length) clearInterval(handler);
}

var handler = setInterval(loop, loop_speed);

Solution 4 - Javascript

I know this is an old question but I stumbled over it, and in the StackOverflow way of doing things I thought I might improve it. You might want to consider a solution similar to what's described here which is known as long polling. OR another solution is WebSockets (one of the better implementations of websockets with the primary objective of working on all browsers) socket.io.

The first solution is basically summarized as you send a single AJAX request and wait for a response before sending an additional one, then once the response has been delivered, queue up the next query.

Meanwhile, on the backend you don't return a response until the status changes. So, in your scenario, you would utilize a while loop that would continue until the status changed, then return the changed status to the page. I really like this solution. As the answer linked above indicates, this is what facebook does (or at least has done in the past).

socket.io is basically the jQuery of Websockets, so that whichever browser your users are in you can establish a socket connection that can push data to the page (without polling at all). This is closer to a Blackberry's instant notifications, which - if you're going for instant, it's the best solution.

Solution 5 - Javascript

Just modify @bschlueter's answer, and yes, you can cancel this poll function by calling cancelCallback()

let cancelCallback = () => {};

var sleep = (period) => {
  return new Promise((resolve) => {
    cancelCallback = () => {
      console.log("Canceling...");
      // send cancel message...
      return resolve('Canceled');
    }
    setTimeout(() => {
      resolve("tick");
    }, period)
  })
}

var poll = (promiseFn, period, timeout) => promiseFn().then(() => {
  let asleep = async(period) => {
    let respond = await sleep(period);
    // if you need to do something as soon as sleep finished
    console.log("sleep just finished, do something...");
    return respond;
  }


  // just check if cancelCallback is empty function, 
  // if yes, set a time out to run cancelCallback()
  if (cancelCallback.toString() === "() => {}") {
    console.log("set timout to run cancelCallback()")
    setTimeout(() => {
      cancelCallback()
    }, timeout);
  }

  asleep(period).then((respond) => {
    // check if sleep canceled, if not, continue to poll
    if (respond !== 'Canceled') {
      poll(promiseFn, period);
    } else {
      console.log(respond);
    }
  })

  // do something1...
  console.log("do something1...");

})


poll(() => new Promise((resolve) => {
  console.log('Hello World!');
  resolve(); //you need resolve to jump into .then()
}), 3000, 10000);

// do something2...
console.log("do something2....")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSologoubView Question on Stackoverflow
Solution 1 - JavascriptFelix KlingView Answer on Stackoverflow
Solution 2 - JavascriptbschlueterView Answer on Stackoverflow
Solution 3 - JavascriptScenView Answer on Stackoverflow
Solution 4 - Javascriptth3byrdm4nView Answer on Stackoverflow
Solution 5 - JavascriptallenylleeView Answer on Stackoverflow