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.
For 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.
