Promise.all()

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

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

Кратко

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

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

Как пишется

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

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

Метод 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'
  })

        
        
          
        
      

На практике

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

yurlovr

Секция статьи "yurlovr"

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

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

        
          
          const peopleIds = [1, 13, 3]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]
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