Telerik blogs
This post originally appeared on the Icenium.com blog.

This is a four part series where we explore some of the tools available to detect and manage online/offline connectivity in web/mobile applications.

The growth of technologies like local storage, and the exposure of certain device APIs — like the camera or geolocation — to the browser (or to a hybrid application) has had an interesting side effect on web developers: the growing need to check the connectivity state of the client. Users are becoming more accustomed to the ability to work seamlessly while disconnected and then synchronize later. In fact, as I write this I'm en route to the AngleBrackets conference, 30k feet in the air with no connectivity on my iPad using Daedalus (an awesome app, btw). But I fully plan to upload this post to my DropBox account when I land. The expectation for this kind of process to just work — maybe a novelty a few years ago — has overwhelmingly become the norm.

The reason(s) you are checking connectivity may vary per the type of application and intent:

  • Your user wants to upload a picture using your hybrid social app, but they're on a train that just entered a tunnel, causing a temporary loss of connectivity. Wouldn't it be great if the upload could simply be queued while potentially alerting the user that their action hasn't been ignored and will be executed as soon as possible?
  • You have a cloud-based IDE or document editor, but the user wants to be able to work while in airplane mode. Sure would be nice if the changes the user has made while offline could get immediately persisted to your back end once the connection is available, right?
  • Your application has a news or stock ticker. You want to keep displaying the most recent data, but perhaps let the user know through some change in the UI that they're currently offline and might not have the latest information.

Regardless of the reason or device - if you're working on web, mobile web or hybrid mobile applications, odds are very high that you will run into the need to check connectivity state on your current or next project. The question is....HOW should you go about it? Lets take a look at some of the APIs available to help you. (Warning: this isn't going to be an all-encompassing list, but a quick tour of some of the more common approaches.)

Window offline/online Event

These events are fired when the browser switches to online or offline - starting on the body, and bubbling up to the document and the window. For a completely contrived example of using the window online andoffline events:

  1. // We simply subscribe to the offline or online event and pass a function (or function reference)
  2. // invoke our handler when the offline event occurs
  3. window.addEventListener("offline", whoopsWeAreOffline);
  4. // and when the online event occurs....
  5. window.addEventListener("online", sweetBackOnLine);

navigator.onLine

The W3C spec description for navigator.onLine is priceless:

Returns false if the user agent is definitely offline (disconnected from the network). Returns true if the user agent might be online…. Note: This attribute is inherently unreliable. A computer can be connected to a network without having Internet access. [emphasis added]

This does not inspire confidence. It's becoming apparent that a clear delineation between "The user said to work offline" and "Oops, we've lost our connectivity" hasn't quite landed with great browser API support yet. Nevertheless, for another contrived example, using the navigator.onLine property:

  1. if (navigator.onLine) {
  2.     sweetWeAreKindaMaybeOnline();
  3. } else {
  4.     uhOhWeAreProbablyButNotDefinitelyOffline();
  5. }

applicationCache downloading/error

The "HTML5 rocks" website has a great post on using applicationCache events (as well as custom XHR response handling) to help indicate online/offline status. It's not sufficient on it's own, entirely – it still doesnt address the "User said to go offline" concern, and should ultimately be used in tandem with other approaches:

  1. window.applicationCache.addEventListener("error", function(e) {
  2.     weMightBeOffline();
  3. });
  4. window.applicationCache.addEventListener("downloading", function(e) {
  5.     weAreProbablyOnline();
  6. });

You might also be interested in reading Jake Archibald's aptly named post: "Application Cache is a Douchebag" (really, read it!).

Cordova/Icenium/PhoneGap Connection Object

If you're building a Cordova/Icenium/PhoneGap application, you can take advantage of thenavigator.connection.type property. Of course, this requires eager checking (it's not an event) - so it's best used in tandem with window online and offline (and possibly other) events.

  1. if (navigator.connection.type === Connection.NONE) {
  2.     weMightBeOffline();
  3. } else {
  4.     whoKnows(); // Could be wifi, cell*, ethernet or unknown
  5. }

Web Socket Connect/Disconnect Event

If you're using a socket library such as socket.io, and you want the socket's connection state to play a part in your application's "online/offline" status, then you can hook into connect and disconnect events (assuming the library you chose provides them). Here's another contrived example, this time using socket.io:

  1. socket.on('connect', function() {
  2.     socketIsOnline();
  3. });
  4. socket.on('disconnect', function() {
  5.     socketIsOffline();
  6. });

Heartbeat Check

Seriously, what more foolproof way to verify connectivity than to actually reach out and try to touch an endpoint? It definitely bypasses the weaknesses of other approaches that could give false positives (I'm looking at you, navigator.onLine). However, this method best demonstrates the need for a dedicated and structured way for your application to determine connectivity state. Think about it — are you going to make a heartbeat check before every request? I hope not! No —what we need is a way to trigger a heartbeat check when something might indicate (or even hint) that our connection might have dropped. The problem, though, is that most applications I've seen tend to only worry about connectivity right when they need to do something with the connection. This leads to if/else branching logic — testing for connectivity — being sprinkled all throughout the app. A better approach, in my opinion, is to separate the concern of connectivity so that it is handled by a dedicated component that can serve as the single source of truth for the app, and event out to other interested components as the state changes. There is an abstraction that is perfect for this, in my opinion: the finite state machine (FSM).

In part 2 of this series, we'll cover what an FSM is, look at some real world examples of them as well as how to create them using machina.js - a helper library for writing FSMs in JavaScript. 


Jim Cowart

About the Author
 is an architect, developer, open source author, and overall web/hybrid mobile development geek. He is an active speaker and writer, with a passion for elevating developer knowledge of patterns and helpful frameworks. Jim works for Telerik as a Developer Advocate and is @ifandelse on Twitter.


Comments

Comments are disabled in preview mode.