Асинхронное ожидание данных массива

#javascript #ajax #asynchronous #async-await

#javascript #ajax #асинхронный #асинхронное ожидание

Вопрос:

По какой-то причине мой асинхронный вызов работает не так, как ожидалось. Вот что я пытаюсь сделать:

  1. Выполните несколько вызовов ajax в цикле
  2. В случае успеха отправьте некоторые данные API в глобальный массив
  3. Используйте этот массив в другой функции (например, распечатайте его)
 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]  'amp;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();
 

Вот JSFiddle с прокомментированным кодом: https://jsfiddle.net/gjv9hrpo/1 /

Я понимаю, что printArr() функция должна запускаться после заполнения массива из-за async характера, который, как я надеялся, решит ожидание. Я использую это неправильно?

Спасибо.

Комментарии:

1. Вы ничего не await делаете в стороне от ajaxCall

2. Ваша функция ajaxCall является асинхронной, но она не ожидает используемый вами метод $.ajax.

3. Попробуйте сделать ajaxCall обещанием, которое разрешается при срабатывании успешного обратного вызова. Вот пример: javascript.info/promise-basics

4. Просто используйте fetch() вместо этого, он уже возвращает обещание, и получение JSON очень просто для загрузки.

5. Потрясающе! await $.ajax({.. я считаю, что это должно быть сделано!

Ответ №1:

Используйте обещание.Все ()

 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]  'amp;structure={"areaCode":"areaCode","cumCasesByPublishDate":"cumCasesByPublishDate"}',
            dataType: "json",
            success: function(data) {
                dict.push(data.data[0].cumCasesByPublishDate);
            }
       }));

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

Комментарии:

1. Вы все еще забыли использовать await ключевое слово.

Ответ №2:

Возможно, имеет смысл сделать это с помощью promises.

Promise.all позволяет узнать, когда либо все входные обещания выполнены, либо когда одно из них отклоняется.

 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}amp;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 выдает вам сигнал, когда все входные обещания выполнены, что означает, что они либо выполнены, либо отклонены. Это полезно в тех случаях, когда вас не волнует состояние обещания, вы просто хотите знать, когда работа будет выполнена, независимо от того, была ли она успешной.

 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}amp;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();