Getting into Gears: Offline Web App Tutorial – Part 2

GearsIn the first part of this tutorial I took a look at some of the background to Gears; the code example showed how to initialise Gears, and create a database (with a table definition). Apologies for the delay in getting the second part out of the drafts section of the blog.

In this section, I’ll show how to use the Gears WorkerPool to carry out operations without affecting the user interface. Also included is a simple example of using the Gears HTTPRequest object to retrieve data from the remote database.

Read the first part of the tutorial.

Using the WorkerPool

The Gears Workerpool allows JavaScript to run in the background without affecting the performance of browser window. This means that the user’s browser won’t slow down or lock up while there is processing going on behind the scenes. This gives the  opportunity to create more intensive scripts, and to have your web application process information while the user carries on with their other work.


// create a workerpool
var workerPool = google.gears.factory.create('beta.workerpool');
// handle messages from the worker
workerPool.onmessage = function(a, b, message) {
console.log('Received message from worker ' + message.sender + ': \n' + message.body);
};
// create a child worker from a URL
var childWorkerId = workerPool.createWorkerFromUrl('/scripts/gears/gears_db_load.js');
// send the child a message... (messageBody, Unique Worker ID)
workerPool.sendMessage("loadAllTreat", childWorkerId);

When the function is called it creates a Workerpool object (more details from the Gears Workerpool API). This is used to create individual Workers that can be set to do different jobs. The Workers do not have access to the Window object, which means that they must interact by sending messages to each other.  The “workerPool.onmessage” callback above is an example of how Workers accept messages from each other (in this case, the details of the message (the Worker that sent it, and the message body) are being written to the Firebug console window.

The line:

var childWorkerId = workerPool.createWorkerFromUrl('/scripts/gears/gears_db_load.js');

is creating a Worker from an external script – gears_db_load.js (more on that in a moment).  The createWorkerFromUrl method returns a unique id value for the Worker – it is using this that the destination of messages sent between Workers is known.

The final line above sends a message to the Worker; in this case, telling it what action to take. The second parameter is the id value of the Worker, which allows the message to be routed to the correct place.

My First Worker


// gears_db_load.js
/*
Workerpool JS to load remote data to local db after Setup
*/
(function(){
var wp = google.gears.workerPool;
var sender; // Parent Worker ID
// handle incoming messages:
wp.onmessage = function(a, b, message) {
try{
var msg = message.body; // what was the message
sender = message.sender; // Where did the message come from
var resp; // response to be returned to the Parent Worker
switch (msg)
{
case 'loadAllTreat':
getAllTreatments(); /* call a function to do something...*/
break;
default:
resp = 'Oops...no message sent!!';
wp.sendMessage(resp, sender);
break;
}
} // try
catch(ex)
{ // send back an error message if needed
wp.sendMessage('Error in worker: '+ err.message, sender);
}
} // onmessage


// handle any errors that come up...
wp.onerror = function( err ){
wp.sendMessage('Error in worker: '+ err.message, sender);
return true;
}

This is creating a new Worker, and uses the onmessage callback to check what message has been passed to it by the sender. A switch statement is used to decide what action is needed, based on the message passed in. In this example, if the message is “loadAllTreat" the function getAllTreatments() is called, otherwise, a message is passed back to the sender.

Also included is an onerror callback that is used to return an error message to the sender, should an error occur.

Gears HTTPRequest

The getAllTreatments() function uses the Gears HTTPRequest to get data from the server using AJAX. The code below demonstrates carrying out the request, and parsing the JSON response from the server. [Note: it stops short of doing anything with the data returned – this will depend on the application in question]

function getAllTreatments(){
var request = google.gears.factory.create('beta.httprequest');
// get Treatment & Treatment Category Data
request.open('GET', '/path/to/my/data/');
request.onreadystatechange = function() {
if (request.readyState == 4) {
try{
response = request.responseText;
var jsResp = json_parse(response); // using http://www.JSON.org/json_parse.js
//...
// do something with the json response, for example, insert it into local database..
//...
}// try
catch(ex){
wp.sendMessage("Worker Error: line - "+ ex.lineNumber + " Ex: "+ ex.message, sender);
} // catch
} // readystate
}; // onstatechange
request.send();
} // getAllTreatments()

The “var request” holds a Gears httpRequest object. It needs a place to request the data from, which is added using “request.open”, and supplying request type (“GET”) the path to the data (‘/path/to/my/data’). When the request completes, the if statement within the onreadystatechange callback is triggered. This parses the response (in this example, the server is supplying a JSON response) using json_parse (available from: http://www.JSON.org/json_parse.js.

The example above stops short of doing something with the response after it has been parsed. One example of what could be done with the data, is to insert it into the local database.

Other Alternatives

There are a number of options available for implementing offline web apps. Some examples include:

Related

This was about: JavaScript
  • Pingback: Getting into Gears: Offline Web App Tutorial - Part 1 | Dave Kelly :: Blog()

  • Ravi

    Hi David,
    Your’s is The best tutorial I have got.
    It’s to the point and very clear to implement.
    I have already implemented sync part for my app but that was without using workerPool module and my app hangs (displays a message that script is busy) and now I know that workerPool will play a major role here.
    So I am going to implement workerPool for sync process by going through your tutorial.

    I’ve a query here :
    How do I access my app offline ?
    Is it the same url which I use for online app (which is in my server : http://www.myserver.com/gerars.html) ?
    I have created a desktop shortcut which works fine (when I do not have internet connnection) but if I refresh my browser (either clicking on refresh icon or ctrl+f5) then it shows ‘no network connection.’ .
    Would you guide me on this.

    Thanks for the tutorial
    Ravi
    ravirkkm@gmail.com

  • http://www.davidkelly.ie Dave

    Hi Ravi,

    Thanks for the comment, glad to hear the tutorial helped!

    Yes, I’d guess the browser hanging is because the sync is using up too many of its resources (which should be helped by moving it to the WorkerPool).

    On the offline usage – the url should be the same one you use for online access. I’m not sure what the issue is when you refresh the browser (why it isn’t loading the off-line version). There is a good article at http://code.google.com/…/take_app_offline.html that gives steps for off-line conversion and tips & caveats that might help…

    Hope that’s of some help.

    Dave.

  • Ravi

    Hi Dave,

    I have implemented sync part using workerPool (thanks alot for your tutorial).
    Thanks for the url for offline use. I am going through it.

    I have a doubt for offline usage:
    Do I have to write script separately for off-line version ?
    I think it’s the same which I implemented for online use….when user goes offline, he/she accesses the same page…right ?
    I don’t have to add separately the script for offline version !

    Thanks,
    Ravi

  • http://www.davidkelly.ie Dave

    Hi Ravi,

    I don’t think you need to write the script separately, but when you’re accessing resources (such as requesting data) there should be a way of checking whether the resource is available online, or if the offline resource (e.g. the local database) should be used.

    When I was doing this, I used a script that acted as a gateway to the data; if the data was not available online, the script used the offline resource. This was based on the Gears article on application architecture.

  • Ravi

    ok…I understood. thanks for explanation.
    Once again, thanks a lot for very useful tutorial (awesome).
    I’ll keep reading your blogs ..attracted me… :-)

    Thanks and Regards,
    Ravi

  • Ravi

    Hi Dave,

    I still have a problem accessing app offline.
    Let me explain how am I doing it so that you can give me some idea:
    I have two files (ggears_c.php and ggears_c.html).

    I have online file ggears_c.php which has php script and gears script (checking if gears installed, activating my site, sync using workerPool, listing data fetched from Local DB and Create Desktop shortcut).
    When user syncs data here (in php file), I am executing HTML file (backend using AJAX) ggears_c.html (for offline use..doing this since when user clicks on ‘Create Desktop Shortcut’ it points to ggears_c.html page and I think this html page data should be in cache for offline use).
    Now when I go offline and click on shortcut, it shows ‘not connected/failed to open…).
    Is there any problem using two files.
    My online file (ggears_c.php) includes headers,jquery,css files.
    Please guide me.
    Waiting for you reply.
    Thanks,
    Ravi