Profile image

Uche's Coding Corner

Passionate about software, technology, personal discoveries, and more.

Improve polling using setTimeOut

Thu Nov 12 2020 🍵 0 min read

setTimeOut and setInterval are very similar in that they perform an action after a given time period. The difference is that setTimeOut executes the function only once. Polling requires that you execute an action/function after a given interval. It is very common to implement polling using the window setInterval property.

For example:

let interval = 0;

function action() {
  console.log('do something here')
}

function poll() {
  interval = setInterval(() => {
    action()
  }, 10000)
}

function clear() {
  clearInterval(interval)
}

poll()

The implementation above is simple, clear, and efficient. It ensures that the action is performed every 10 seconds. However, if the action is a request to the server and the server is slow, you could have multiple requests pending because setInterval will execute after the given time has elapsed, whether the previous call has been completed or not. We can mitigate this issue easily using setTimeout.

function action() {
  // mimic slow server
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
    resolve('do something here')
  }, 10000)
  })
}

function poll() {
  interval = setTimeout(async () => {
    await action()
    poll()
  }, 10000)
}

Now we will only poll the action again after the previous one has been completed.

Bonus

You might want to poll the action only if the page is visible to the user or the browser tab is active. This is where window event listener visibilitychange comes in handy. visibilitychange is triggered each time the browser tab is active or inactive. In the handler of the event listener, you can check for the browser tab visible using document.hidden or document.visibilityState.

For example:

document.addEventListener("visibilitychange", function() {
  if (document.hidden) {
    clear()
  } else {
    poll()
  }
});

Pretty simple!

Here's the full code for you to try out:

let interval = 0;

function action() {
  // mimic slow server
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
    resolve('do something here')
  }, 10000)
  })
}

function poll() {
  interval = setTimeout(async () => {
    const response = await action()
    console.log(response)
    poll()
  }, 10000)
}

function clear() {
  clearInterval(interval)
}

document.addEventListener("visibilitychange", function() {
  if (document.hidden) {
    clear()
  } else {
    poll()
  }
});

poll()
javascript
performance