sonic boom
sonic boom

Reputation: 904

Consolidated result object from a sequence of getJSON() calls

I'm using jquery after a long time. I've a requirement in which I need to call a few Rest APIs to fetch some data from each API. Then out of the result of all calls create a consolidated resultant object.

Something like this:

Output I'm looking for:

result {
    a: 123,
    b: 456, ....
    z: 789
}

Pseudo:

var result = {}; // final object containing consolidated result
$.getJSON(restapi1, function (data) {
    result["a"] = data.total;
});

// next rest call to fetch b
$.getJSON(restapi2, function (data) {
    result["b"] = data.total;
});

// so on...
// after fetching all values and storing them in one result object access elements like
var value1 = result.a;

I know I can use Promise.all(), but it gives an array as output & I want to avoid looping over it to fetch required element.

Please suggest. Thank You.

Upvotes: 2

Views: 75

Answers (2)

Sirko
Sirko

Reputation: 74046

I'd approach this somewhat like follows:

// a wrapper for the basic retrieval functionality
async function getTotal( param ) {
  const res = await $.getJSON( param.url );
  return { name: param.name, total: res.total };
}

async function getData() {
  // start all requests
  // api list contains entries like { name: 'a', url: restapi1 }
  const reqs = apilist.map( url => getTotal )

  // wait for all requests to finish
  const resp = await Promise.all( reqs );

  // convert to the output format
  return resp.reduce( (el,all) => { all[el.name] = el.total; return all; }, {} );
}

getData().then( (result) => /* ... */ );

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074425

I know I can use Promise.all(), but it gives an array as output

True, but you don't have to use the result it provides. You can use side-effects as you did in your pseudocode.

If your various $.getJSON calls are all written individually, this is a use case for jQuery's $.when:

var result = {}; // final object containing consolidated result
$.when(
    $.getJSON(restapi1, function (data) {
        result["a"] = data.total;
    }),
    // next rest call to fetch b
    $.getJSON(restapi2, function (data) {
        result["b"] = data.total;
    }),
    // ...
).done(function() {
    // use `result`
});

If you have a loop instead, using $.when is possible but awkward:

var result = {}; // final object containing consolidated result
var promises = [];
for (/*...*/) {
    promise.push($.getJSON(/*...*/));
}
$.when.apply($, promises).done(function() {
    // use `result`
});

...so in that situation Promise.all is probably better provided you can assume it's present in the environment (natively, or because you polyfill it or use an enhanced promise lib):

var result = {}; // final object containing consolidated result
var promises = [];
for (/*...*/) {
    promise.push($.getJSON(/*...*/));
}
Promise.all(promises).done(function() {
    // use `result`
});

Upvotes: 3

Related Questions