Val's Blog
Lots of stuff for Web 2.0 freaks and Javaholics
Feeds RSS | Atom | RDF
 
 
Ed Yourdan: "There is nothing in the programming field more despicable than an undocumented program."
[ Login ]

December 2007
SunMonTueWedThuFriSat
       1 
 2  3  4  5  6  7  8 
 9  10  11  12  13  14  15 
 16  17  18  19  20  21  22 
 23  24  25  26  27  28  29 
 30  31      
Nov  |  Today  |  Jan
XML Feeds   Subscribe with Bloglines

Javaranch Sheriff   My LinkedIn Profile
Drop me a line or two   Bloglines Blogroll
JavaRSS   Referers
How cool are you?   My Reviews

Next trips...
SpringOne 2008 (Jun 11-12, 08)
Ajax Exp. 2008 (Sep 29-Oct 1, 08)
Top 10 entries (#hits)
(As of Nov 30, 2007)


Top 10 entries (#hits/day)
Come Back (5.032)
(As of Nov 30, 2007)
Recent Blog Entries
Recent Blog Comments
Re: Review of "Marketing Management 12th"
i know marketing management by kotler is good book but the problem is that the management part of this book is totally missing as fare as i know managemet is complete different subject and it should not be mixed i am student of MBA i was looking at ass...

Re: Review of "Pro Spring"
Using simple POJOs + factories without Spring for "echo" and "counter" would be a lot more easier. No need to write those XML files... So, in this case using Spring makes me write a lot more code... (OK, you can generate everything with the help of And...

pls urgent
Hi I am trying to generate the word doc but i m not understanding wats happening any one pls figure it out /* * WordAPI.java * * Created on May 30, 2006, 10:50 AM * * To change this template, choose Tools | Template Manager * and open the te...
Archives (# entries)
Links
Other Blogs
Other Blogs

Reviewing
Reading
Locations of visitors to this page
What they once said...
 

It should come as no surprise to any well-informed Web 2.0 developers out there that the Ajax tech box can quickly morph into Pandora's box if not handled with care. This is mainly due to the fact that the XMLHttpRequest object offers a great flexibility to the developer as to when and how often HTTP connections to remote servers can be initiated. As is often the case, this increased flexibility in managing the web application connectivity usually implies an additional cost when it comes to making sure that the communication layer is kept clean and the remote servers are not put under an unnecessary heavy and potentially lethal load.

Experience has shown that web developers are more concerned about knowing when they have to initiate new connections than thinking about the conditions under which they should have to abort them. What this means is that basically very few developers make use of the XMLHttpRequest.abort() method. Worse, sometimes developers are aware of the problem and would like to make use of abort(), but they can't because the JavaScript framework/library they use does not provide support for it. Even worse, sometimes the framework/library does provide that kind of support but additional plugins of that framework/library deceptively break the contract.

On some project, we are using the jQuery JavaScript library and a host of jQuery plugins for enriching jQuery's core to best suit our needs. jQuery provides excellent support for Ajax by means of its general-purpose utility function called jQuery.ajax(). Other utility functions, such as jQuery.get() and jQuery.post() are merely facades that eventually call jQuery.ajax() for doing their work. All those utility functions return the XMLHttpRequest object that was used to make the Ajax request, so that the developer can get her hands on it, shall she have to abort the request manually.

One of the plugins we are using is the jQuery Form plugin. One of the useful features of that plugin is to provide a way to ajaxify any HTML form using the ajaxSubmit() method. The good thing with ajaxSubmit() is that it makes a good job of setting up and wrapping the call to jQuery.ajax(). However, the bad thing is that it breaks the contract of jQuery.ajax() in that it doesn't return the XMLHttpRequest object but the wrapped form element instead. Thus, there is no way the developer can abort a request initiated using ajaxSubmit().

There are many ways to solve this problem. One of them is to modify the Form plugin to return the XMLHttpRequest object but this would most probably break all the existing client code base. A second option is to use AOP in order to weave additional behavior into existing code. There are several solutions for doing AOP in JavaScript, but since we are using the jQuery library, it's nice to know that there is an AOP plugin for jQuery.

Basically, the jQuery AOP plugin provides very primitive support for weaving before, around and after advice into existing code as well as removing any previously weaved advice. Even though this plugin does not provide full-fledged AOP capabilities (i.e., no introduction support, no aspect modularization support, no wildcards in pointcut expressions), it is lightweight (943 bytes!!) and it does cover our need, which basically consists of wrapping all calls to jQuery.ajax() for registering the returned XMLHttpRequest object after letting the call proceed. The reason we have to be able to abort all ongoing Ajax requests is due to our page architecture. All pages are loaded by Ajax calls and other Ajax calls may happen once a given page chunk is loaded. When the user requests a new page, there is no reason to let any ongoing Ajax call proceed because the results eventually received from the server would not be used anyway. So, we have to cancel all ongoing calls.

In terms of implementation, our need would be covered by the following code. Our code is actually a little more involved than that, but the following code basically shows the main ideas of what we wanted to achieve:

var ajaxRequests = [];

//registers all unterminated Ajax requests
function registerAjaxRequests() {
	var advice = function(invocation) {
		var ajaxRequest = invocation.proceed();
		if(ajaxRequest.readyState < 4) {
			ajaxRequests.push(ajaxRequest);
		}
		return ajaxRequest;
	}

	$.aop.around({target: jQuery, method: 'ajax'}, advice);
}

// abort pending ajax requests
function abortAjaxRequests() {
	while (ajaxRequests.length > 0) {
		var ajaxRequest = ajaxRequests.shift();
		if (ajaxRequest.readyState != 4) {
			ajaxRequest.abort();
		}
	}
}

The job of the registerAjaxRequests() function is to instrument all calls to jQuery.ajax() and to store a reference to the newly created XMLHttpRequest object in the case we need to abort it at some later time (e.g. when a new page request has been made by the user). This function can be called anytime but we usually call it when the current page is loaded using jQuery's $(document).ready(...) handler.

The other function called abortAjaxRequests() can be invoked anytime existing Ajax requests need to be aborted. It will iterate over the array that contains the existing XMLHttpRequest objects and will invoke abort() on each of them if the call has not returned yet.

So, using the jQuery AOP plugin that heavily builds upon the dynamic and reflective nature of the JavaScript language, we could very easily get around a design flaw in the jQuery Form plugin which would prevent us from getting hold of the XMLHttpRequest object for aborting ongoing Ajax calls. I really do hope that the jQuery AOP plugin will eat some meat and provide a richer set of AOP functionalities in the future. But for now, it provides more stuff than we actually need.

 
About this Blog