3

I'm using jQuery ajax to request data which will then be made into different kinds of charts or tables.

I've put the queries I want to run into an object and send the requests. runQuery() returns a jQuery promise. The data returned when the promise is done is correct. [Edit]Since the ajax requests run asynchronously they may not come back in the order they were issued [/EDIT] and I have no way of know which query the returned data was for.

function refreshData(){
    for(var key in baseQueries){
        runQuery(baseQueries[key])
            .done(function(data){
                console.log("Query data for "+key);
                // want to call different charting functions
                // based upon which results are returned
            });
    }
};

runQuery(obj) { // "public" function
    var params = $.extend({},defaults,obj);
    return sendRequest(queryUrl,params)
}

sendRequest(url,data,method){ // "private" function
    method = method || "GET";

    return $.ajax({
            type:method,
            url:url,
            dataType:"json",
            data:data
        })
        .fail(function(error){
            console.log(error);
        });
}

In this case the console logs the value of key during the last iteration over the baseQueries object. For example if there are three items in my baseQueries object and the the last item in my baseQueries object is

"This-is-the-last-query":"queryparam1,queryparam2,etc"

Then when all three of the ajax calls resolve I get three logs of "This-is-the-last-query". Which is not helpful because it doesn't tell me which query the data belongs to.

This is similar to the idea of the infamous javascript loop issue but I really don't see how the answer of attaching the value to a DOM element could be used here.

How do I match up which query call goes with which promise? How to I pass the key through the ajax call and return it with the promise data.

Edit Don't think this is a duplicate of the indicated thread. I see how they are related, but not how to use that to solve this. Suggested duplicate doesn't mention jquery, ajax, promises, or asynchronous issues. It is also marked as a duplicate for another thread that doesn't mention any of those things either.

The solution shown either involves using the dom element to hold the information (which doesn't apply here) needed for the onclick or by adding a closure, but I don't see how to do that when there is already data being returned.

Community
  • 1
  • 1
Rothrock
  • 1,413
  • 2
  • 16
  • 39
  • The `key` value in the callback needs to come from `data` response e.g. `data.key`. – Jasen Dec 31 '15 at 20:06
  • @Jasen and how would I do that? The data is returned from the $.ajax call and I don't know how to change what comes back from the server. – Rothrock Dec 31 '15 at 21:17
  • show that runQuery code here perhaps? – Mark Schultheiss Dec 31 '15 at 21:26
  • 1
    Reword your question to be: "How to retrieve a value which changes for each ajax call" - because what you really want is the "key" value for each ajax call which i think this will do: https://jsfiddle.net/ecpprfpv/ – Mark Schultheiss Dec 31 '15 at 22:29
  • Thanks that does work! It seems a little magical to me, like out of the blue this has a myKey property and if I was looking at the code would I be able to figure out that "this" is the $.ajax() call. But hey it works, right? – Rothrock Dec 31 '15 at 23:15
  • If you explain what "myLastQuery" is in your code then this question could be reopened. I don't think it's a duplicate but it's also not clear what the problem is in code because of this. – 2rs2ts Dec 31 '15 at 23:20
  • @Rothrock - to understand the "this" here, study the jQuery object creation code. – Mark Schultheiss Jan 01 '16 at 15:32

2 Answers2

1

if you want to check if jquery promise is resolved you can check with jqueryPromise.state() which returns either pending, resolved or rejected depending on state.
If you are sending multiple ajax requests and you want to know when they are completed you can put them into array ([$.ajax(...),$.ajax(...)]) and pass it to $.when like

var requests = [$.ajax(...),$.ajax(...)];
$.when.apply($, requests).done(function() {
  console.log('all requests completed');
});

if you want to build something complex with promises I would suggest using bluebird or less complex rsvp

Bek
  • 3,157
  • 1
  • 17
  • 28
1

If you pass jQuery ajax a parameter that it knows nothing about, it ignores it and you can access it later.

Here we set a parameter for your extra value (mykey) then we have access to it later for the instance we are using:

function refreshData() {
  for (var key in baseQueries) {
    runQuery(baseQueries[key], key)
      .done(function(data) {
        console.log("Query data for " + this.myKey);
       // "this" here is the ajax for which the promise (ajax) gets resolved,
       // and we return that promise so it works here.
        // want to call different charting functions
        // based upon which results are returned
      });
  }
};

runQuery(obj,key) { // "public" function
  var params = $.extend({}, defaults, obj);
  return sendRequest(queryUrl, params,,key)
}

sendRequest(url, data, method, key) { // "private" function
  method = method || "GET";

  return $.ajax({
      type: method,
      url: url,
      dataType: "json",
      data: data,
      myKey:key
    })
    .fail(function(error) {
      console.log(error);
    });
}
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100