Silveryahoo: Don’t you want to see Yahoo! Silverlight Mail? Bill Burke wants to get rid of Java!
Feb 03

Checking the network to handle offline applications

Gears, Tech with tags: Add comments

One of the common questions we here in Gears land is, how to handle checking if an application is online or offline. This is a trickier problem that you may think at first. What does it mean to be offline?

The Autodesk guys talked about this a little in their interview. They have the notion of online and offline, which is just a flag. They then have the notion of connected or disconnected, which they test at regular intervals.

Mathew Foster recently posted the code that he uses to handle this situation. He basically ported the Dojo Offline work to Prototype, and you end up with a library that you can use like this:

var netCheck = new NetworkDetection("blank.php");
 
netCheck.addEventListener("online", function(eAja) {
  $("display").innerHTML = "online";
});
netCheck.addEventListener("offline", function(eAja){                                          
  $("display").innerHTML = "offline";                                      
});

Some other folks also put their thoughts out there.

Firstly, Dimitri Glazkov (who is on fire recently btw) posted his monitor script:

    // provides connection monitoring
    // controller
    function Monitor() {
 
        var me = this;
 
        //  triggered when connection changes
        //  sends as parameter:
        //      online : Boolean, true if connection became available,
        //          false if connection is broken
        this.onconnectionchange = nil;
 
        // starts the monitoring
        this.start = function() {
            try {
                wp = google.gears.factory.create('beta.workerpool', '1.0');
            }
            catch(e) {
                return false;
            }
            wp.onmessage = function(a, b, message) {
                if (message.sender == id) {
                    // only two messages: 
                    // first [f]ailure to connect 
                    // or back [o]nline
                    var text = message.text;
                    if (text == 'f') {
                        me.onconnectionchange(false);
                    }
                    else if (text == 'o') {
                        me.onconnectionchange(true);
                    }
                }
            }
            id = wp.createWorker(String(worker) + ';worker()');
            // send a message to the worker, identifying owner's id
            wp.sendMessage(window.location + '?poll', id);
            return true;
        }
 
        function worker() {
            var POLLING_INTERVAL = 2000;
 
            var wp = google.gears.workerPool;
            var url;
            var parentId;
 
            var first = true;
            var online;
 
            var timer = google.gears.factory.create('beta.timer', '1.0');
 
            wp.onmessage = function(a, b, message) {
                url = message.text;
                parentId = message.sender;
                poll();
            }
 
            function poll() {
                var request = google.gears.factory.create('beta.httprequest', '1.0');
                request.open('HEAD', url);
                request.onreadystatechange = function() {
                    if (request.readyState == 4) {
                        try {
                            if (request.status == 200) {
                                if (!online) {
                                    online = true;
                                    wp.sendMessage('o', parentId);
                                }
                            }
                        }
                        catch(e) {
                            if (online || first) {
                                online = false;
                                first = false;
                                wp.sendMessage('f', parentId);
                            }
                        }
                        wp.sendMessage('d', parentId);
                        timer.setTimeout(poll, POLLING_INTERVAL);
                    }
                }
                try {
                    request.send();
                }
                catch(e) {
                    if (online) {
                        online = false;
                        wp.sendMessage('f', parentId);
                    }
                }
            }
 
        }
 
        function nil() {}
    }

Gears co-lead Aaron Boodman also put his hat in the ring with a solution that uses the Gears HttpRequest object, and a clean use of onerror:

function monitorOnlineness(url, onlinenessChanged) {
 var interval = 1000; // check network once a second
 var onlineness = null;
 var timer = google.gears.factory.create('beta.timer');
 var timerId = null;
 
 function check() {
   timerId = timer.setTimeout(function() {
     var req = google.gears.factory.create('beta.httprequest');
     req.onload = function() { onlinenessChanged(true); }
     req.onerror = function() { onlinenessChanged(false); }
     req.open("HEAD", url);
     req.send(null);
   }, interval);
 }
 
 function updateOnlineness(val) {
   if (onlineness !== val) {
     onlineness = val;
     onlinenessChanged(val);
   }
   check();
 }
 
 function cancel() {
   if (timerId) {
     timer.clearTimeout(timerId);
   }
 }
 
 return cancel;
}

You quickly find that there are many solutions, and that they depend on what you really need to do for your application use case. I am still personally hopeful that an 80% solution is placed into Gears itself as a starting point….

One Response to “Checking the network to handle offline applications”

  1. Matthew Foster Says:

    Hey Dion,

    Great stuff in this post, thanks for referencing my work with gears. I think it’d be good to show all 3 libs implementation for doing the same things, ie updating a DOM node to display the status. With the source code it can be difficult to see how one can use it for a particular case, but with the implementation it’d be much easier to see how you can leverage the library to make things easier for you in the long run.

    Regards,
    Matt

Leave a Reply

Spam is a pain, I am sorry to have to do this to you, but can you answer the question below?

Q: What are the first four letters in the word British?