У меня проблема, которую я не могу решить.

Представляя следующее

if (users) {
 for (var i = 0; i < users.length; i++) {
  apiData.users = getUserDetails(users[i]);
 }
}

А также

if(profiles) {
 for (var i = 0; i < profiles.length; i++) {
  apiData.profiles = getProfileDetails(users[i]);
 }
}

Теперь, только после того, как оба этих блока кода были завершены (т.е. вызовы API вернули требуемые результаты), хотел бы я сделать что-то вроде этого

for (var i = 0; i < users.length; i++) {
 saveUserProfile(apiData)
}

Обычно я обрабатываю подобную ситуацию, помещая первый блок кода в функцию, которая возвращает обратный вызов, а затем запускаю третью функцию после этого, но как я могу это сделать, когда фактически выполняются две отдельные операции?

Чтобы было понятно, я бы не хотел сохранять пользователей и профили отдельно, для этого есть разные причины.

Я хотел бы знать, есть ли какой-либо стандартный способ справиться с такой ситуацией, поскольку могут быть или не быть пользователи или профили, поэтому использование обратных вызовов, похоже, не сработает?

0
Ryan de Kock 7 Янв 2017 в 16:16

1 ответ

Лучший ответ

Для этого можно использовать модуль async. Используйте функцию async.parallel(), поскольку ваш первый и второй фрагменты не зависят друг от друга и могут выполняться асинхронно, но вы хотите, чтобы третий фрагмент выполнялся, когда выполнение первого и второго завершено.

Если предположить, что users, profiles и apiData уже объявлены, ваш код будет выглядеть

function func1(callback){
  if (users) {
   for (var i = 0; i < users.length; i++) {
    apiData.users = getUserDetails(users[i]);
   }
  }
  //invoke callback 
}

function func2(callback){
  if(profiles) {
   for (var i = 0; i < profiles.length; i++) {
    apiData.profiles = getProfileDetails(users[i]);
   }
  }
  //invoke callback
}

var asyncfunc = [];
asyncfunc.push(func1);
asyncfunc.push(func2);

async.parallel(asyncfunc,function(err,result){
  //result is an array which receives the second argument of each function's callback.
  for (var i = 0; i < users.length; i++) {
    saveUserProfile(apiData)
  }
})


ИЗМЕНИТЬ
PS: здесь вы также можете использовать async.series (). В данном случае оба эквивалентны, поскольку функции, обрабатываемые здесь async.parallel(), не используют таймеры и не выполняют задачи ввода-вывода.

callback в каждой функции внутри массива принимает два аргумента. Первый аргумент представляет ошибку, которая равна null, если ошибок нет, второй представляет результат функции, который передается второму аргументу обратного вызова функции async.parallel().

0
Ritik Saxena 7 Янв 2017 в 21:02
Благодарность! Я никогда раньше не использовал async, но, похоже, вам нужно всегда возвращать обратный вызов с функциями в async.
 – 
Ryan de Kock
7 Янв 2017 в 18:15
Простите. Я соответственно отредактировал ответ. спасибо за указание :)
 – 
Ritik Saxena
7 Янв 2017 в 21:07