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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 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 */