A Better Web Timer for an Improved User Experience

August 28, 2015

This article explains the potential pitfalls with standard web timers, and offers a small, free drop-in replacement: setVisiTimeout()

Done!

"The only reason for time is so that everything doesn't happen at once" – Albert Einstein

Timers For All The Things!Timers Are Everywhere

When building a web app, developers often make use of timers. Timers allow programmatic events based on an elapsed time. This can be used in very visible ways, such as a notification popup that hides itself after some amount of time; or in less visible ways, such as a resource load timeout.

But what about when the user isn't watching our page? Perhaps they have tabbed to a different window, or minimized the browser to use some other app. Or maybe they've even put their device to sleep.

The result is often a poor user experience.

setTimeout()

Conventional web timers make use of the javascript setTimeout function. When a timer is set and the user diverts their attention away from the page, one of two things happen:

  1. The timed event triggers after the specified amount anyway and any attached action occurs away from the user's view.
  2. Or, the javascript thread is suspended. Once the user returns, any timers that should have completed while the thread was suspended are triggered immediately.

In either case, the behavior is likely undesired. 

For example, if the timer is being used for a notification that should be displayed for 10 seconds and then hidden, the user needs to have a chance to read it. Which means what we really want is 10 seconds of user visibility. Ideally, if the user stops viewing the page, the timer should pause; and then resume once the user returns.

setVisiTimeout()

This behavior is exactly what you get with setVisiTimeout() - a function you can copy/paste into your apps and use in place of setTimeout() to provide a better user experience.

It uses the Page Visibility API to detect visibility events, such as the user minimizing the browser, switching to another tab, or hiding the browser window with another app.

See it in Action

Clicking the blue button below will turn it red for 4 seconds, and then it will return to blue. It is using setVisiTimeout() so modern browsers will pause if you hide this window:

 

About That Resource Loading Timer

Some readers may be wondering about that resource timer I mentioned in the first paragraph. What might that have to do with page visibility? 

In the case of mobile browsers, like Safari on iPhone, the browser suspends all network activity for the page not being viewed. So for resources that use setTimeout() to give up on the resource (such as in requireJS), this is a common scenario:

  1. Browser requests a resource - sets a timer so it can report to user if resource doesn't load.
  2. User switches to another tab, thereby suspending the original tab and all network activity.
  3. After some time, the user returns to the first page.
  4. The browser re-activates the environment and checks to see if any timers should have expired during suspension period.
  5. Browser triggers resource timer causing the app to report a problem to the user and cease attempting to load resource.
  6. Sad face.

So use setVisiTimeout() for resource loading timeouts as well if you can. If you are using a resource loader such as requireJS, you can set the timeout to 0 and then wire up your own setVisiTimer() event that checks to see if the resource loaded and if not, notify the user.

Ok, here is the code for setVisiTimeout(). It is also available at GitHub.

Loading Gist...

Compatibility

This has been tested in a handful of browsers, and seems to work well in those that support the PageVisibility API. Those that don't fall back to using a standard timer. It even supports IE8 (though this page doesn't render properly - to see IE8 working, see this test page.)

Note: The visibility event does not fire if the browser window is partially covered. Additionally, there is obviously no way to know if the user is simply distracted and looking away or has left their chair for a coffee refill. Design accordingly! ;-)


If you or your organization could use a somewhat fanatical developer on your current or next project, lets talk. I am passionate about the user experience, easy to work with, and I get stuff done. Lets build something great!


A Better Web Timer for an Improved User Experience Tweet This!
Glenn is the founder of bluejava K.K., and has been providing consulting services and developing web/mobile applications for over 15 years. Glenn lives with his wife and two children in Fujisawa, Japan.
Comments

No comments yet. You can get the conversation going!

Add Comment
Displayed alongside comment
Optional. Not displayed, but used for avatar
Optional
Don't enter anything here: