1

I have a list of numbers and I want to create an array of JSON objects with created from querying the numbers from an api. For example, if the numbers are

numbers = [1, 4];

Then I want a JSON object created like such:

[{
  number: 1,
  data: $.getJSON('/api/numbers/1')
},
{
  number: 4,
  data: $.getJSON('/api/numbers/4')
}]

The simplest way I would think would be to map the list of numbers to a corresponding JSON object:

numbers_data = numbers.map(n => {number: n, data: $.getJSON('/api/numbers'+ n)})

However, once I have the numbers_data with the embedded $.getJSON promises, I'm not sure how to tell when all the api calls have completed. Is there a pattern that would let me tell when the variable numbers_data is fully resolved so that I can do something with it?

  • You could `$.when` to "combine" the promises into one and then attach a callback to know when everything is done. – gen_Eric Jul 11 '16 at 20:56
  • In the end, do you want your object to contain the promise or the JSON data returned from the AJAX call?] – gen_Eric Jul 11 '16 at 20:57
  • possible duplicate of [How do you work with an array of jQuery Deferreds?](http://stackoverflow.com/q/4878887/1048572)? – Bergi Jul 11 '16 at 21:05
  • I want the object to contain the data returned. Yea, here is what I had using `$.when` but I felt that it was too complicated: promises = numbers.map(function(n){ return ($.getJSON('numbers/'+n)); }) datasets = numbers.map(function(n){ return {number: n, data: null}; }); $.when(promises).then(data) { for(var i=0; i – danield9tqh Jul 11 '16 at 21:07
  • If jqueries promises are 'thenable' you can use ES6 Promise.all. – ste2425 Jul 11 '16 at 21:07

1 Answers1

0

You can use $.when to basically "combine" the promises into one. You can then attach a .done() handler to the output of $.when and know once all your AJAX calls are done. You can then access all the returned JSON data and use it/build your object as needed.

Something like this:

var promises = [],
    numbers_data = numbers.map(number => {
        var data = $.getJSON('/api/numbers'+number);

        promises.push(data);
        return {number, data};
    });

// This will let you know once *all* promises are resolved.
$.when.apply($, promises).done(() => {
    // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
    for(var i = 0, len = arguments.length; i < len; i++){
        numbers_data[i].data = arguments[i][0];
    }
});
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
  • That's the solution I had originally, I was just wondering if there was a more functional way to do it. Although ultimately this might end up being the simplest solution anyway. – danield9tqh Jul 11 '16 at 21:12
  • 1
    @Daniel _"I was just wondering if there was a more functional way to do it"_ What do you mean by "more functional"? – guest271314 Jul 11 '16 at 21:16
  • 1
    Cleaner nowadays to replace $.when.apply() with Promise.all(). Results in `then()` is true array of only the response data – charlietfl Jul 11 '16 at 21:59