5

I have an ajax call that might take a bit to complete. I don't want to use async:false because I want it to stay non blocking code. So I decided to use Q. The problem is I don't understand how ca I extract the json that came back from Q.when($.ajax...). I'm new to Q.

In this example I would like the variable to hold the json that came back from the server:

    var res = Q.when($.ajax({
    type: "POST",
    url: "GetData.asmx/GetMembersList",
    contentType: "application/json; charset=utf-8",
    dataType: "json"
    }));

return res;
Itay.B
  • 3,991
  • 14
  • 61
  • 96

2 Answers2

16

With asynchronous calls you can't just assign the result to a variable, because that result won't exist until sometime in the future. Q.when does not return the result, it returns a promise object that will eventually resolve with a result.

If there is only ever one thing you want to do with the JSON you could just inline a .then call to get the result.

Q($.ajax({
  type: "POST",
  url: "GetData.asmx/GetMembersList",
  contentType: "application/json; charset=utf-8",
  dataType: "json"
})).then(function (res) {
  // res now contains the JSON
});

However the real power of promises comes with the fact that you can pass them around and use them later.

function getMembersList() {
  return Q($.ajax({
    type: "POST",
    url: "GetData.asmx/GetMembersList",
    contentType: "application/json; charset=utf-8",
    dataType: "json"
  }));
}

var membersList = getMembersList();

membersList.then(function (res) {
  // once the AJAX call completes this will
  // run. Inside this function res contains the JSON
  return res; // pass res to the next chained .then()
}).then(function (res) {
  // you could chain another then handler here
});

// do some other stuff

membersList.then(function (res) {
  // you could also add another then handler later too
  // even long after the AJAX request resolved and this
  // will be called immediately since the promise has already
  // resolved and receive the JSON just like the other
  // then handlers.
});

You don't need to use Q if you don't have other reasons for using it, since version 1.5 jQuery returns a deferred object from AJAX calls. A Deferred is similar to a promise. Q does offer more power and jQuery's promises/deferreds don't exactly implement the Promises/A standard, potentially causing problems with error handling. For something simple like an AJAX call jQuery promises are usually good enough if you are already using jQuery anyway.

var membersList = $.ajax({
  type: "POST",
  url: "GetData.asmx/GetMembersList",
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

membersList.then(function (res) {
  // res now contains the JSON
});
Community
  • 1
  • 1
Useless Code
  • 12,123
  • 5
  • 35
  • 40
  • Perfect explanation! I finally understand how it works. – Itay.B Mar 09 '14 at 13:52
  • just wanted to know I'm getting this right, so in the memberlist code, getMemberList ajax call is called, then the script executes the first "then", and then it excutes "do some other stuff" and then it executes the second "then"? Or when you make the ajax call, it executes the ajax, then the first "then", then the second "then" skipping the "do some other stuff" code? – sksallaj Sep 17 '15 at 02:12
  • Things execute in source order. `then` executes right away, however since the AJAX call is asynchronous, the anonymous function *callbacks* inside the `.then()` call are not executed until after the AJAX request resolves. So, what will actually happen is the "do other stuff here" code will execute right away when it is encountered and then sometime later after the AJAX request resolves the `then` callbacks will execute. [This fiddle](http://jsfiddle.net/UselessCode/9j6mL1t5/) should hopefully make it more clear. – Useless Code Sep 17 '15 at 03:58
1

Here are some examples from the q documentation about using with jQuery ajax.

return Q(jQuery.ajax({
    url: "foobar.html", 
    type: "GET"
})).then(function (data) {
    // on success
}, function (xhr) {
    // on failure
});

// Similar to jQuery's "complete" callback: return "xhr" regardless of success or failure
return Q.promise(function (resolve) {
    jQuery.ajax({
        url: "foobar.html",
        type: "GET"
    }).then(function (data, textStatus, jqXHR) {
        delete jqXHR.then; // treat xhr as a non-promise
        resolve(jqXHR);
    }, function (jqXHR, textStatus, errorThrown) {
        delete jqXHR.then; // treat xhr as a non-promise
        resolve(jqXHR);
    });
});

https://github.com/kriskowal/q/wiki/Coming-from-jQuery

Hope that helps.

pedalpete
  • 21,076
  • 45
  • 128
  • 239