Promise.all()

Запускаем несколько промисов параллельно и ждём, когда они все выполнятся.

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

Метод all() — это один из статических методов объекта Promise. Метод all() используют, когда нужно запустить несколько промисов параллельно и дождаться их выполнения.

Как пишется

Секция статьи "Как пишется"

Promise.all() принимает итерируемую коллекцию промисов (чаще всего — массив) и возвращает новый промис, который будет выполнен, когда будут выполнены все промисы, переданные в виде перечисляемого аргумента, или отклонён, если хотя бы один из переданных промисов завершится с ошибкой.

Метод Promise.all() возвращает массив значений всех переданных промисов, при этом сохраняя порядок оригинального (переданного) массива, но не порядок выполнения.

Как понять

Секция статьи "Как понять"

Успешное выполнение нескольких промисов

Секция статьи "Успешное выполнение нескольких промисов"

Создадим несколько промисов:

        
          
          const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 2000))const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 1000))
          const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))
const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 2000))
const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 1000))

        
        
          
        
      

Передадим массив из созданных промисов в Promise.all():

        
          
          Promise.all([promise1, promise2, promise3])  .then(([response1, response2, response3]) => {    console.log(response1)    // 1    console.log(response2)    // 2    console.log(response3)    // 3  })
          Promise.all([promise1, promise2, promise3])
  .then(([response1, response2, response3]) => {
    console.log(response1)
    // 1
    console.log(response2)
    // 2
    console.log(response3)
    // 3
  })

        
        
          
        
      

Если передать пустой массив, то Promise.all() будет выполнен немедленно.

Один из промисов завершился ошибкой

Секция статьи "Один из промисов завершился ошибкой"

Если хотя бы один промис из переданного массива завершится с ошибкой, то Promise.all() тоже завершится с этой ошибкой. Метод уже не будет следить за выполнением оставшихся промисов, которые рано или поздно все-таки выполнятся, и их результаты будут просто проигнорированы.

В примере ниже, промис promise2 завершается с ошибкой:

        
          
          const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))const promise2 = new Promise((resolve, reject) => setTimeout(() => reject('error'), 2000))const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 1000))Promise.all([promise1, promise2, promise3])  .then(([response1, response2, response3 ]) => {    console.log(response1)    console.log(response2)    console.log(response3)  })  .catch(error => {    console.error(error)    // error  })
          const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))
const promise2 = new Promise((resolve, reject) => setTimeout(() => reject('error'), 2000))
const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 1000))

Promise.all([promise1, promise2, promise3])
  .then(([response1, response2, response3 ]) => {
    console.log(response1)
    console.log(response2)
    console.log(response3)
  })
  .catch(error => {
    console.error(error)
    // error
  })

        
        
          
        
      

В итоге обработчик then() будет проигнорирован, и будет выполняться код из обработчика ошибок catch().

Не промисы в массиве промисов

Секция статьи "Не промисы в массиве промисов"

Если в Promise.all() передать не промисы, он вернёт переданные не промисы в массив результатов как есть (под капотом при этом произойдёт его преобразование с помощью метода Promise.resolve()).

Передадим в Promise.all() промис promise1, число number и объект obj:

        
          
          const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))const number = 2const obj = {key: 'value'}Promise.all([promise1, number, obj])  .then(([response1, response2, response3]) => {    console.log(response1)    // 1    console.log(response2)    // 2    console.log(response3.key)    // 'value'  })
          const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))
const number = 2
const obj = {key: 'value'}

Promise.all([promise1, number, obj])
  .then(([response1, response2, response3]) => {
    console.log(response1)
    // 1
    console.log(response2)
    // 2
    console.log(response3.key)
    // 'value'
  })

        
        
          
        
      

На практике

Секция статьи "На практике"

Роман Юрлов советует

Секция статьи "Роман Юрлов советует"

🛠 Довольно частое использование — это преобразование массива с данными в массив с промисами с помощью map(). В map() для каждого элемента создаётся промис, а затем полученный массив передаётся в Promise.all(). Это позволит дождаться выполнения всех промисов, а затем обработать результат.

Например, можно использовать метод Promise.all() для получения данных нескольких персонажей из вселенной звёздных войн через запрос к API:

        
          
          const peopleIds = [1, 13, 3]const arrayFetchUsers = peopleIds.map(user => fetch(`https://swapi.dev/api/people/${user}`).then((response) => response.json()))Promise.all(arrayFetchUsers)  .then((responses) => {    // responses — массив результатов выполнения промисов    responses.forEach(resp => {      console.log(resp.name)    })  })  .catch(error => {    console.error(error)  })
          const peopleIds = [1, 13, 3]
const arrayFetchUsers = peopleIds.map(user => fetch(`https://swapi.dev/api/people/${user}`).then((response) => response.json()))

Promise.all(arrayFetchUsers)
  .then((responses) => {
    // responses — массив результатов выполнения промисов
    responses.forEach(resp => {
      console.log(resp.name)
    })
  })
  .catch(error => {
    console.error(error)
  })

        
        
          
        
      

Пример сначала сделает три запроса к API, с помощью Promise.all() дождётся их завершения и парсинга ответа в JSON, а затем выведет имя персонажа для каждого. В консоли появится:

Luke Skywalker
Chewbacca
R2-D2