Функция возвращается до обработки данных

Я думал, что циклы for блокируются в Javascript, но эта функция возвращает пустой массив до завершения цикла for. Является ли ответ на этот вопрос установкой новой функции только с циклом for в качестве обещания? Если да, то на что это похоже, синтаксис обещания меня действительно сбивает с толку.

async function retrieve_s3_file(to_do_list, guid){
  var data_list = [];

  for (let i = 0; i < to_do_list.length; i++)
  {
    element = to_do_list[i];
    console.log("\n\nOutgoing request /jobs/list?guid=" + guid + "&file=" + element);
    axios.get(job_queue_url + "?guid=" + guid + "&file=" + element)
    .then(function (res){
      data_list.push(res.data);
      console.log("Inside Loop: " + JSON.stringify(data_list));
    })
    .catch(function (error){
      console.log(error);
    });
  }

  console.log("Data List: " + JSON.stringify(data_list));
  return JSON.stringify(data_list);
}

Отвечает ли это на ваш вопрос? Как вернуть ответ на асинхронный вызов, который ссылается на Как я могу получить массив URL-адресов с помощью Promise.all?

ggorlen 22.04.2022 22:54
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
2
1
39
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Javascript является однопоточным, и поэтому циклы обычно блокируются, но в этом случае ваши обещания поместят новые задачи в конец стека. Если вы используете await, новая задача не должна создаваться, и она должна вести себя так, как вы хотите. Но вы делаете это sycronus, поэтому он будет немного медленнее, чем раньше.

async function retrieve_s3_file(to_do_list, guid){
  var data_list = [];

  for (let i = 0; i < to_do_list.length; i++)
  {
    element = to_do_list[i];
    console.log("\n\nOutgoing request /jobs/list?guid=" + guid + "&file=" + element);
    await axios.get(job_queue_url + "?guid=" + guid + "&file=" + element)
    .then(function (res){
      data_list.push(res.data);
      console.log("Inside Loop: " + JSON.stringify(data_list));
    })
    .catch(function (error){
      console.log(error);
    });
  }

  console.log("Data List: " + JSON.stringify(data_list));
  return JSON.stringify(data_list);
}

Это сработало, спасибо

aggie0642 23.04.2022 00:47

axios.get это обещание. В javascript обещание не блокируется, что означает, что обратный вызов, указанный в функции then, будет запущен после разрешения обещания. Но обещание не заблокирует поток.

Приведенный ниже пример отражает проблему вопроса. Консоль печатает startend, а затем ok. Поскольку customPromise — это обещание, и оно вызывается без await, вызывающая сторона не будет ждать для завершения этого обещания, поэтому вызывающая сторона продолжит выполнение и напечатает end. Обратите внимание, что это обещание выполняется немедленно, но обратный вызов res => console.log(res) будет выполнен в конце, потому что это обратный вызов обещания.

const customPromise = new Promise((resolve, reject)=>{resolve('ok')})


function nonBLockingExample (){
  console.log('start');
  customPromise.then(res => console.log(res));
  console.log('end');
}

nonBLockingExample();

Ниже приведен пример желаемого результата. Вызывающий ждет для разрешения customPromise, потому что customPromise вызывается с ключевым словом await.

const nonBlockingPromise = new Promise((resolve, reject)=>{resolve('ok')})

async function bLockingExample (){
  console.log('start');
  await nonBlockingPromise.then(res => console.log(res));
  console.log('end');
}

bLockingExample();

Итак, чтобы применить исправление к вашему коду, просто подождите axios.get. (await axios.get(.....)

Спасибо за объяснение. Итак, просто чтобы убедиться, что я понимаю, поскольку обещание Axios является асинхронным, Javascript выполняет остальную часть функции, а затем ждет ответа от обещания после возврата функции? Это моя проблема?

aggie0642 23.04.2022 00:49

Если вы используете асинхронную операцию, она не будет блокироваться.

Вы можете использовать ключевое слово await, если хотите, чтобы Axios ждал завершения запроса, в противном случае используйте обещания. Соберите их и с помощью Promise.all вы сможете получить все ответы в виде массива, когда все запросы будут разрешены.

async function retrieve_s3_file(to_do_list, guid) {
  const requests = [];
  for (const file of to_do_list) {
    const params = new URLSearchParams({ guid, file });
    const request = axios.get(`${job_queue_url}?${params.toString()}`);
    requests.push(request.then((response) => response.data));
  }

  return Promise.all(requests).then(JSON.stringify);
}

Другие вопросы по теме