My single page web application makes several REST style calls to my server. Jquery $.ajax is the tool of choice for implementing this on the browser-side. When converting from Jquery version 1.4 to 1.7+ I started to follow a their new coding pattern. Here’s the old way, the new pattern and a little gotcha (the jquery ajax always parameters are inconsistent depending on success condition) that I write-up here for my reference and potentially the benefit of others.
Old mode of operation using jquery 1.4 $.ajax syntax:
$.ajax({"url":RestURI, "type":"GET", "dataType":"text", success: function(data) { // Do success stuff // 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: */ });
New pattern using jquery 1.7 uses the chainable done(), fail(), and always() Promise methods derived from the jQuery Deferred object. .See code snippet below for the general case for how I use it. It’s pretty straight forward.
// Start spinner // start logging timer $.ajax({"url":RestURI, "type":"GET", "dataType":"text"}) .done( function(data, textStatus, jqXHR) { // Do success stuff }) /* end done: */ .fail( function (jqXHR, textStatus, err) { // Do error stuff }) /* end fail */ .always( function() { // stop logging timer, do logging // stop spinner }); /* End always */
The new $.ajax pattern lets me have multiple always, done and fails; so I thought it would be good to add a .always at the top — something I would run first before a done or fail. Well, I discovered that the ajax always parameters are inconsistent; that is, the always function returns two different sets of parameters depending on how the $.ajax function returned. If the ajax function failed, then the always callback parameters were (jqXHR, textStatus, err ); if the ajax function was successful, the always callback parameters were flipped: (err, textStatus, jqXHR ).
So if you want to use the always function, then I recommend you setup a callback with no parameters or you do a test of the textStatus parameter — “success” This quirk got me a couple of times. I found references to it on the jQuery bug list — this behavior is by design. The code snippet below captures the issue. This is not a show stopper; the new promise paradigm is pretty cool and I have some cases where I am chaining together multiple ajax calls, where this will come in really handy.
// Start spinner // start logging timer $.ajax({"url":RestURI, "type":"GET", "dataType":"text"}) .always( function(arg1, textStatus, arg3 ) { // on fail: always( function(jqXHR, textStatus, err ) { and textStatus != "success" // on done: always( function(err, textStatus, jqXHR ) { and textStatus == "success" console.log("First Always function. textStatus="+textStatus+"\n"); }) /* end always (top) */ .done( function(data, textStatus, jqXHR) { // Do success stuff }) /* end done: */ .fail( function (jqXHR, textStatus, err) { // Do error stuff }) /* end fail */ .always( function() { // stop logging timer, do logging // stop spinner }); /* End always */