09.22.07
AJAX closures done well
First what is a closure?
A closure is a function that returns without completing itself, and which still holds local variables at their old state. It’s pretty neat and handy when you see what they can do. Here’s an example of the town of Tinyville, population 5. A new resident moves in, but the census starts before he signs a lease.
var population = 5;
function fun(count) {
return function() {
alert(”count is “+count);
}
}
setTimeout(fun(population), 1000);
population++;
document.writeln(population);
Result:
6
Alert: 5
The six is written to the screen, but the old value of the population is saved by the setTimeout and the closure function, fun.
Closures are so important that reading the wrong tutorial will doom the AJAX writer. Here’s an example from Apple’s AJAX tutorial,
req.onreadystatechange = processReqChange; // DOOMED!!
req is a global variable. That’s really bad, since the chance to use a closure has past and no more than one request at a time may occur. So much for asyncronous. One alternative is to tag each outbound url, such as “http://localhost/ajax.php?population=5″. That will save the state, but that’s not as good as saving whole objects or sets of local variables. The MDC tutorial at Mozilla gets it right. Here’s the crucial line with my population variable injected.
httpRequest.population = 25;
httpRequest.onreadystatechange = function() { alertContents(httpRequest); } // BETTER
Why is this better?
You can tack on any variable to httpRequest and it will be separate from other requests. For instance “httpRequest.population=5″ is a valid way to preserve needed variables. Later the population is used.
if (httpRequest.status == 200) {
alert(httpRequest.responseText + “population is “+httpRequest.population);
} else {
alert(’There was a problem with the request.’);
}
One final reason to use closures is that AJAX is asynchronous, so you are not guaranteed to receive responses in the same order as the requests were dispatched. This makes using a closure especially valuable.