0

I'm trying to make 2x Ajax calls at the same time (async) with jQuery, like the following:

function displayAccount() {
    $.when(doGet("accounts/1", null),
           doGet("orders/1", null))
        .done(displayAccountSuccess);
}

function displayAccountSuccess(accountJson, ordersJson) {
  console.Info(accountJson);
  console.Info(ordersJson);
}

When I do this, the displayAccountSuccess is called BEFORE the 2x doGet's are called/handled. Of course, the values of the two method arguments are undefined.

So obviously my doGet isn't returning a promise :(

For that method...

function doGet(endpoint, queryString)
{
    var url = ApiWebsite + "/" + endpoint;
    if (queryString)
    {
        url += "?" + queryString;
    } 

    var authorizationHeader = isAuthenticated()
        ? "bearer " + localStorage.getItem(LocalStorageJwt)
        : "";

    $.ajax({
        url: url,
        headers: {
            authorization: authorizationHeader
          }
    })
    .done(function(json)
    {
         return json; 
    })
    .fail(function(data1, data2){ 
        displayError("fail");
    }).promise();
}

Ok - now this is what is interesting :) the ajajx.done method DOES have the correct json response in there! So I -thought- I was returning that json data back to the caller.

Now, if i change the code from:

$.ajax(....

to

return $.ajax(....

the when.done(..) function is delayed and only called after the 2x ajax calls are completed! Yay! ..but ... the VALUE of this data is an array of 3 items .. the data, successTest, jqXHR :( Sure, I can just get the json value from array slot 0 (accountJson[0]) but this means I'm not understanding something pretty basic here :(

I'm hoping that my done() method will accept 2x json objects only, not the full SUCCESS (or failure) array.

I hope this makes sense :blush:

Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • You may take a look [here](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Madhavan.V Dec 14 '17 at 12:51
  • Just need to `return $.ajax(...)`, by default, JavaScript functions return undefined – mhodges Dec 14 '17 at 22:07
  • So... your question is quite confusing. What exactly are you asking? Your title asks why done is being called immediately, but it's obvious you already know why that is happening. That question infact is a duplicate, but... the content of your question seems to be asking something entirely different, which is also a duplicate but of something else. Did you edit your question to ask an entirely new question instead? – Kevin B Dec 14 '17 at 22:09
  • No I didn't edit it. I'm not sure _why_ the `done` is being called immediately. I can _fluke_ fixing the code to do what i want BUT it's not doing what I _exactly_ want. So - as I said in the title -> `done` isn't being called immediately and I'm hoping someone might be able to use my code example to explain what _my code_ is doing wrong _and why_. Also, the _fluke_ means I don't understand why that works - hence the question and asking for help. – Pure.Krome Dec 15 '17 at 10:45

1 Answers1

1

Use then to return a promise and filter what gets returned

function doGet(endpoint, queryString)
{
    var url = ApiWebsite + "/" + endpoint;
    if (queryString)
    {
        url += "?" + queryString;
    } 

    var authorizationHeader = isAuthenticated()
        ? "bearer " + localStorage.getItem(LocalStorageJwt)
        : "";

    return $.ajax({
        url: url,
        headers: {
            authorization: authorizationHeader
          }
    })
    .then(function(json) {
         return json; 
    }, function(){ 
        displayError("fail");
    });
}

The thing is that the done() returns the actual deferred object, so you will always get the same arguments in subsequent .done callbacks. You cannot return from it.

The then will return a new promise, so what it returns is what will be used in the chain from that point on.

See a small demo (https://jsfiddle.net/5cm3grg3/) that exhibits your problem and then un-comment the then part to see it work correctly.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • 1
    @downvoter i would appreciate a comment for why you think this is a bad suggestion. – Gabriele Petrioli Dec 14 '17 at 21:56
  • It is incorrect. or at the least, it doesn't solve the problem the OP is having. `displayAccountSuccess` will still occur before both requests are complete because `doGet` doesn't return a promise. the .done and .then are both irrelevant, since it doesn't alter the result. – Kevin B Dec 14 '17 at 22:02
  • 1
    @keviB you mean the missing `return` right? Fair point, it was my mistake as the OP had already figured they needed it, i thought the code included it. Updated the answer. – Gabriele Petrioli Dec 14 '17 at 22:05
  • The issue is the OP simply doesn't understand the output hey are getting. The fact that they're getting an array of arrays `[[data, status, xhr],[data, status,xhr]]`. That however is simply how $.when works, it's well documented in the jquery documentation. When you pass multiple promises into .then, the results of them will be presented as an array. – Kevin B Dec 14 '17 at 22:07
  • @KevinB i have *kind of* addressed that at the end of my post (*i hope*) – Gabriele Petrioli Dec 14 '17 at 22:07