Tahmid
Tahmid

Reputation: 185

Async await on array data

For some reason my async call is not working as expected. Here's what I'm trying to do:

  1. Make several ajax calls in a loop
  2. On success, push some API data to a global array
  3. Use that array in another function (e.g print it out)
var authcodes = ["E06000001","E06000002","E06000003"];
var dict = [];

async function ajaxCall() {
    for(var i=0;i<authcodes.length;i++){
        $.ajax({
           type: "GET",
           url: 'https://api.coronavirus.data.gov.uk/v1/data?filters=areaCode=' + authcodes[i] +'&structure={"areaCode":"areaCode","cumCasesByPublishDate":"cumCasesByPublishDate"}',
            dataType: "json",
            success: function(data) {
                dict.push(data.data[0].cumCasesByPublishDate);
            }
       });

    } return dict;
}

async function printArr () {
    const someApiRes = await ajaxCall()
    console.log(someApiRes[1]); //this doesn't work
    console.log(dict[1]); //this doesn't work

}

printArr();

Here is the JSFiddle with code commented: https://jsfiddle.net/gjv9hrpo/1/

I understand that the printArr() function has to be ran after the array is populated due to the async nature which I hoped the await would solve. Am I using it wrong?

Thanks.

Upvotes: 0

Views: 769

Answers (2)

ksav
ksav

Reputation: 20830

It might make more sense to do this with promises.

Promise.all lets you know when either all input promises have fulfilled or when one of them rejects.

var authcodes = ["E06000001", "E06000002", "E06000003"];

function ajaxCalls() {
  return Promise.all(
    authcodes.map((code) => {
      return new Promise(async (resolve) => {
        const response = await fetch(
          `https://api.coronavirus.data.gov.uk/v1/data?filters=areaCode=${code}&structure={"areaCode":"areaCode","cumCasesByPublishDate":"cumCasesByPublishDate"}`
        )
        const json = await response.json();
        resolve(json.data[0].cumCasesByPublishDate);
      });
    })
  );
}

function printArr() {
  ajaxCalls().then((values) => {
    console.log(values);
  }).catch(e => {
    console.error(e)
  });
}

printArr();

Promise.allSettled gives you a signal when all the input promises are settled, which means they’re either fulfilled or rejected. This is useful in cases where you don’t care about the state of the promise, you just want to know when the work is done, regardless of whether it was successful.

var authcodes = ["E06000001", "E06000002", "E06000003"];

function ajaxCalls() {
  return Promise.allSettled(
    authcodes.map((code, i) => {
      return new Promise(async (resolve, reject) => {
        if (i ===0 ) reject('something went wrong')

        const response = await fetch(
          `https://api.coronavirus.data.gov.uk/v1/data?filters=areaCode=${code}&structure={"areaCode":"areaCode","cumCasesByPublishDate":"cumCasesByPublishDate"}`
        );
        const json = await response.json();
        resolve(json.data[0].cumCasesByPublishDate);
      });
    })
  );
}

async function printArr() {
  const results = await ajaxCalls();
  console.log(results.map((result) => result.value || result.reason));
}

printArr();

Upvotes: 0

ControlAltDel
ControlAltDel

Reputation: 35096

Use promise.All()

async function ajaxCall() {
  var promises = [];
    for(var i=0;i<authcodes.length;i++){
        promises.push($.ajax({
           type: "GET",
           url: 'https://api.coronavirus.data.gov.uk/v1/data?filters=areaCode=' + authcodes[i] +'&structure={"areaCode":"areaCode","cumCasesByPublishDate":"cumCasesByPublishDate"}',
            dataType: "json",
            success: function(data) {
                dict.push(data.data[0].cumCasesByPublishDate);
            }
       }));

    }
    await Promise.all(promises); 
    return dict;
}

Upvotes: 1

Related Questions