Completed a big task on Friday, though not the way I wanted it – background, auto synchronisation of notes (including changes, deletions, etc) between server and browser app.
HTML5 has introduced the powerful features that provide in-built features for managing actions such as synchronisation when the browser detects an internet connection.
[sourcecode language=”javascript”]
if(navigator.online){
//do sync here
} else {
//store data offline
}
document.body.addEventListener("online", function () {
// do sync here
}, false);
document.body.addEventListener("online", function () {
// store data offline
}, false);
[/sourcecode]
Unfortunately, these features aren’t completely supported, or even uniformly implemented across browsers and, thus, are hardly usable in the current state.
All server requests in my app are implemented through xhr. So, I’m tapping into it and using this workaround:
- If an xhr call fails, an alternate function is called which:
- Sets a global variable to ‘offline‘
- Calls equivalent local functions which edit/create/delete/list from localStorage
- Starts a daemon using setInterval() that checks every sends a ‘Ping‘ xhr request to check if a server connection is available again
- When the daemon can connect to server, it:
- Sets the global variable to ‘online‘
- Starts a function that syncs all local changes to server and then downloads a fresh list from server
- Kills the daemon using clearInterval() call
There are quite a few problems with this approach. The ones I’m worrying about right now are:
- Memory, CPU and battery usage by that artificial daemon, specially on mobile devices.
- Unnecessary load on the server from handling those Ping requests, even though there’ll be only one successful one for every connect.
Though, compared to the browser ‘online / offline’ properties, this approach has one advantage too – it can also handle instances when the internet connectivity is up but my server / app is down.
One change I’ll probably be doing is fetching only the header instead of pinging the app and checking result – It’s faster and might be lighter on the server (need to check this bit). Got the idea for this from this blog post.
[sourcecode language=”javascript”]
x.open(
// requesting the headers is faster, and just enough
"HEAD",
// append a random string to the current hostname,
// to make sure we’re not hitting the cache
"//" + window.location.hostname + "/?rand=" + Math.random(),
// make a synchronous request
false
);
[/sourcecode]
Still, that doesn’t make up for a native browser capability to tell the app when the network connection has gone down. Waiting for it…
P.S.: A word on the sync function implementation. I’ve implemented them as self-recursive functions that create asynchronous xhr calls till all changes have been sync’ed or the connection goes down again. The other alternative is, of course, to make them synchronous and put them inside a loop. I prefer to keep them async, but there’s one small problem with it – before I start the final sync’ed list download, I can not be sure that all the async calls have completed and it is really the fully updated list that I’m downloading. Is there a work around to that?