Совет JS: #1 – async/await на массивах

Предположим, что по какой-то причине мы обходим массив с помощью метода map() и нам нужно запустить асинхронную функцию на каждом из элементов. Что-то вроде следующего:

const users = ['user1', 'user2', 'user3']
const data = users.map(async (user) => await fetchApiData(user))
Войдите в полноэкранный режим Выход из полноэкранного режима

Здесь нам нужно понять, что фиктивная функция fetchApiData (которая получает в качестве параметра имя одного из пользователей) будет осуществлять асинхронный вызов внешнего API, с которым работает наше приложение.

Что произойдет, если мы теперь запишем содержимое переменной data через консоль? Ну, мы найдем что-то вроде следующего:

const users = ['user1', 'user2', 'user3']
const data = users.map(async (user) => await fetchApiData(user))

console.log(data)
/*
[
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]
*/
Войдите в полноэкранный режим Выход из полноэкранного режима

То есть, выполнение кода не останавливается в ожидании результатов вызова внешнего API, и поэтому данные массива будут образованы таким количеством элементов, сколько пользователей мы объявили в массиве users и связали с каждой из позиций объект JavaScript Promise в состоянии ожидания.

Разрешение всех вызовов параллельно.

Первый вариант решения этой проблемы – использовать метод all() объекта Promise JavaScript, который позволит всем обещаниям, которые он получает в качестве параметра (этот метод ожидает получить в качестве параметра массив обещаний, которые необходимо разрешить), выполняться параллельно, не завися друг от друга, и не завершит свое выполнение, пока все эти обещания не будут выполнены.

const users = ['user1', 'user2', 'user3']
const data = await Promise.all(
    users.map(async (user) => await fetchApiData(user))
)

console.log(data)
/*
[
  dataFromUser1,
  dataFromUser2,
  dataFromUser3
]
*/
Войдите в полноэкранный режим Выход из полноэкранного режима

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

Последовательное разрешение пламени.

Но что произойдет в случае, если у нас есть зависимость в выполнении обещаний, то есть, что вызовы асинхронной функции (в нашем примере внешний API будет зависеть от результата предыдущего вызова)? В этом случае мы должны использовать структуру для ... из следующим образом:

const users = ['user1', 'user2', 'user3']
const data = []

for (const user of users) {
    data.push(await fetchApiData(user))
}

console.log(data)
/*
[
  dataFromUser1,
  dataFromUser2,
  dataFromUser3
]
*/
Войдите в полноэкранный режим Выход из полноэкранного режима

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

Оцените статью
Procodings.ru
Добавить комментарий