navigator.onLine considered harmful
After several abortive attempts of trying to use HTML5 Application cache, I decided to turn Greptweet into an offline capable Web application and I learnt a ton along the way.
If you have code in your application that looks like:
if (navigator.onLine) {
// Do something server side
} else {
// Do something locally
}
You are probably doing it wrong. Why?
The navigator.onLine attribute is inherently unreliable. "A computer can be
connected to a network without having Internet access." as
http://developers.whatwg.org/offline.html#browser-state says and as my
suckless compatriots point out: Aside from physical
link state, there is no way to tell the difference between an 'offline'
network and a highly latent one. Again physical link state doesn't help you
if your cable connected to your router is offline or you use wireless.
Microsoft determines Internet connectivity by pinging one of their
servers(!).
It gets worse if you are a luser because if you
are sane and shun bloatware like dbus and
the bonkers Network Manager then
navigator.onLine will simply not report false on a typical Linux
distribution like
Debian or
Archlinux when offline. Linux
Chrome's
navigator.onLine implementation for example depends on
org.freedesktop.NetworkManager
to work.
Whilst developing under Archlinux, Firefox's "Work offline" feature was a god send. Though Chrome's developer tools is much better to examine the Application Cache under the Resources section.
So what's the alternative to using navigator.onLine? I think individual Web
apps need to determine navigator.onLine themselves by doing a http request to
their Web site and if you don't get a 200 in x seconds you set your own
navigator.onLine variable to false. I know at least one Web
signage application that does this already.
It's obviously important for a public sign to stay robust and work offline in
the case of spotty internet connectivity.
After writing Greptweet with Offline HTML Appcache features, I don't think I need grep.php anymore. So another approach is to rely on sync using the cache manifest and localStorage, and design your Web application not to act on application data remotely.
Update via Twitter of course:
@kaihendry I've experimented with offline-first approach - always read from offline and sync in a worker thread emitting events @annevk
— Michael Mahemoff (@mahemoff) July 16, 2012
@kaihendry Cool. Chrome actually refused to add navigator.online for a long time on the basis it's better to check yourself.
— Michael Mahemoff (@mahemoff) July 16, 2012