Monthly Archives: December 2013

jqueryWriteLessDoMore120213

$.ajax logging using Ajax Global Events. Re-factoring Single Page Web Application

Background on $.ajax logging using Ajax Global Events:  So I’ve moved from jQuery 1.4 to 1.9. I have some time to refactor my code to take advantage of some of the new features of 1.9 and to get ready for 1.10; the next jQuery release removes some of the deprecated methods.

For this round of coding, I am focusing on the $.ajax() method. In my present design, my single page web application makes REST calls for many of the UI menu items. For example, a click on the FILE->LOAD menu item triggers a function call to code that retrieves a file from my server. The basic pattern is like this:

// Start spinner
// start logging timer
$.ajax({"url":RestURI,
 "type":"GET",
 "dataType":"json",
 success: function(data) {
 // Do success stuff (parse, format and display)
 // stop logging timer, do logging
 // stop spinnger
 }, /* end success: */

 error: function (req, stat, err) {
 // Do error stuff
 // stop logging timer, do logging
 // stop spinner
 } /* end error: */
});

I have more than 7 code blocks that follow this pattern. Since the success/error/complete callback functions have been deprecated and I need to touch the code anyways, I thought I’d use the newish $.ajax() global events handlers  to clean up my code. The event handlers seem to be a useful place to put common pieces of code that really shouldn’t have been so liberally cut-and-pasted when I wrote the original code.

jQueryIcon120213For each of my ajax code blocks, I put a generous amount of logging in. Maybe this logging should only be needed when writing/debugging the code, but for me, since I spend so little dedicated time on this application, I wanted to keep verbose logging on always to make it real easy for me to debug.

$.ajax logging using Ajax Global Events

The following new block of code is doing my $.ajax logging using Ajax Global Events.

$(document).ajaxSend(function(evt, xhr, settings) {
 console.log(settings.type+" "+settings.url+" Sent");
 start = new Date().getTime();
 // Other logging
});
$(document).ajaxSuccess(function(evt, xhr, settings) {
 console.log(settings.type+" "+settings.url+" Success");
 // Other logging
});
$(document).ajaxError(function(evt, xhr, settings, exc) {
 console.log( settings.type+" "+settings.url+" Failed. "
 +xhr.status+"-"+xhr.statusText);
 // Other logging
});
$(document).ajaxComplete(function(evt, xhr, settings) {
 console.log(settings.type+" "+settings.url+" Complete");
 end = new Date().getTime();
 diff = end - start;
 // Other logging
});

As you can see, the ajaxSend/ajaxSuccess/ajaxError/ajaxComplete events are fired in sequence at the $.ajax() function executes and after the  .done(), .fail() and .compete() callbacks are executed.

The “Other logging” comment represents 2 or 3 lines of code where I put logging information into a user visible menu item (REPORTS->LOG) where I can see even more details without having to open the console window. For me, this effort is a nice clean out some of the logging stuff, to make the application logic a little more visible;  this clears up a bunch of clutter for me.

New-ish .done/.fail/.always Callbacks

Therefore, my $.ajax() code blocks are straighten out to follow the new done/fail/always callbacks. Here’s an example new $.ajax() code block:

// Start spinner
$.ajax({url:RestURI,
 type:"GET",
 dataType:"json"})
 .done( function(data, textStatus, jqXHR) {
 // Do success stuff
 }) /* end done: */

 .fail( function (jqXHR, textStatus, err) {
 // Do error stuff
 }) /* end fail */

 .always( function() {
 // stop spinner
 }); /* End always */

Some things to note: I still put the start/stop spinner function calls inline. I may move this to the global even handlers, but not yet.

Deferred Objects

Also, the done/fail/always call backs follow the new Deferred Object model. This will then let me setup some promise objects to let me address some of the async race conditions I have in my application.

For example, I have a case where I can run FILE->SAVE and then run REPORT->General and the report will produce results before the save was completed. I know how to fix this, but I was looking to use my new ajax code blocks architecture to get some practice with promise objects instead… for next time.