Thursday, 12 November 2009

Learning Closure. Ajax with goog.net.*

This blog is moving to caprazzi.net.

Google released closure library, a javascript library good to make rich internet applications.

As this is going to be an important library in software developement, I decided to try it. 'Ajax' networking is a good starting point, so I looked into the package goog.net and found two promising classes, HxrIo and XhrManager, which I used for my tests.

The documentation is clear but sometimes shy about who does what. Fortunately there are plenty of links to the source code, which is well written and documented.

The interesting code is below, but there's a more extend version of my closure-library tests.

Just hit a url without waiting for a response

// load the modules
goog.require('goog.net.XhrIo');
goog.require('goog.Uri');

// the easy way: static function call with no callback
goog.net.XhrIo.send('url/');

// using the send() method of an instance.
new goog.net.XhrIo().send('urlA'); // GET, default
new goog.net.XhrIo().send('urlB', 'POST');

// also works with an Uri object
var uri = new goog.Uri('urlC');
new goog.net.XhrIo().send(uri, 'PUT');

// no http method validation, this is a valid call
new goog.net.XhrIo().send('urlF', 'XXXX');

// send some data with the POST, works as expected
new goog.net.XhrIo().send('urlG', 'POST', 'p1=v1&p2=v2);

// ATTENTION data will not be attached to a GET
// so this call won't do what you may expect.
new goog.net.XhrIo().send('urlH', 'GET', 'p1=v1&p2=v2');

Request data from the server

// an html file as text
goog.net.XhrIo.send('sample.html', function(event) {
 var text = event.target.getResponseText());
});

// an xml file as document object
goog.net.XhrIo.send('sample.xml', function(event) {
 var document = event.target.getResponseXml());
});

// a json file as javascript object
goog.net.XhrIo.send('sample.json.js', function(event) {
 var data = event.target.getResponseJson());
});

// spot the 404
goog.net.XhrIo.send('gone_fishin', function(event) {
 var success = event.target.isSuccess()); // false
 var status = event.target.getStatus()); // 404
 var statusText = event.target.getStatusText()); // not found
});

// !!! exceptions in the callback are swallowed, so check your conditions
// (there is interesting error handling stuff in goog.debug.*)
goog.net.XhrIo.send('gone_fishin.js', function(event) {
 // I expected some data, but the file is not there
 // and this will raise an exception...
 var data = event.target.getResponseJson();
 var field_data = data.field;
 // ...so this statement will not execute...
 alert('bonk');
 // ...BUT you won't see anything in your console.
});

// a 404 using an XhrIO instance and closure event management;
var io = new goog.net.XhrIo();
goog.events.listen(io, goog.net.EventType.COMPLETE, function(event) {
 var status = event.target.getStatus()); // 404
});
io.send('gone_fishin');
Using the connection manager

goog.require('goog.net.XhrManager');

// goog.net.XhrManager(opt_maxRetries, opt_headers, opt_minCount, opt_maxCount, opt_timeoutInterval)
var mgr = new goog.net.XhrManager(2, null, 0, 2);
goog.events.listen(mgr, goog.net.EventType.COMPLETE, function(event) {
 // this is fired once for each send(), even if they are retried
 var xhr = event.xhrIo;
});
mgr.send('id_one','closure.js');
mgr.send('id_two','/urlTwo');
mgr.send('id_three','/urlThree');
mgr.send('id_four','/urlFour');

// reusing an id before the request is complete, causes an exception...
try { mgr.send('id_one','/x'); }
catch (e) { /*[goog.net.XhrManager] ID in use*/ }

// ...unless the connection is aborted
mgr.abort('id_one');
mgr.send('id_one','/x');

mgr.send('other_id','/someurl', null, null, null, function(event) {
 // it's ok to reuse an id an after the request completed
 mgr.send('other_id', '/fool');
});

This blog is moving to caprazzi.net.