Tag Archives: promise methods

Jquery ajax always parameters order inconsistent

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 */