Для автора это первая в жизни статья написанная где-либо и когда-либо.
Вступление
Цель данной статьи рассказать о жизненном цикле Promise и о отличиях методов all vs any vs race vs allSettled.
В данном тексте нет ничего супернаучного, поэтому могу предположить что статья расчитана на Junior+.
Кратко
new Promise(resolve, reject) => {})
.then(onFulfilled, onRejected)
.catch(onRejected);
Promise.all(array);
Promise.any(array);
Promise.race(array);
Promise.allSettled(array)
Жизненный цикл Promise
Исходя из документации мы можем говорить что инстанс Promise имеет несколько динамически изменяемых сущностей:
State - может быть в трех состояниях,
pending
,fulfilled
иrejected
;Fate - бывает в двух состояниях,
unresolved
илиresolved
;Settled - имеет два состояния
settled
иunsettled
.
Cразу после создания, промис находится в состоянии pending
, следующим шагом может быть три варианта, первые два которые я упомяну это resolve(any)
и reject(any)
, последним мы разберем resolve(thenable)
.
resolve(any)
- переводим промис в состояниеfulfilled
, вызываемonFulfilled
;reject(any)
- переводим промис в состояниеrejected
, вызываемonRejected
;resolve(promise)
- если в качестве аргумента мы передадим вresolve
другой промис то мы отложимresolve
основного промиса до тех пор, пока не выполнится вложенный, а точнее пока он не станетsettled
, т.е. пока не перейдет в состояниеfulfilled
илиrejected
.
состояние | завершен? | установлен? | |
new Promise() | pending | - | - |
resolve(promise) | pending * | resolved | - |
resolve(any) | fulfilled | resolved | settled |
reject(any) | rejected | resolved | settled |
Пояснение:
Состояние - это сущность промиса, которая изменяется на протяжении его жизни в направлении от pending до fulfilled или rejected.
Завершен - это сущность промиса которая говорит о том, завершена ли работа текущего промиса (resolved), которая определяется вызовом метода resolve или reject, важно понимать что завершение работы не значит что значение установлено.
Установлен - это сущность промиса которая говорит о том, установлено ли значение для этого промиса, речь идёт о аргументах переданных в resolve или reject.
Отдельное внимание стоит обратить на случай, когда в качестве аргумента, в resolve передаётся значения в виде thenable объекта, в таком случае состояние основного промиса остается pending но при этом основной промис считается resolved, дальнейшая судьба основного промиса перекладывается на этот новый объект, и "значение" основного промиса будет равно "значению" thenable.
Сравнение all vs any vs race vs allSettled
Несколько промисов в один можно объеденить c помощью статических методов класса Promise:
all - нужны все выполненные
дожидаемся пока все промисы из
array
будут выполнены, вonFulfilled
мы получаем массив результатов в том же порядке в каком были установлены промисы в начальном массиве;в случае если хоть один промис из
array
будет отклонён, вonRejected
мы получим причину первого отклоненного промиса.
any - нужен хотя бы один выполненный
дожидаемся когда хотя бы один промис из
array
выполнится, вonFulfilled
мы получаем результат первого выполненного промиса;в случае если все промисы из
array
будут отклонены, вonRejected
мы получим AggregateError: All promises were rejected.
race - нужен первый завершенный
дожидаемся когда любой промис из
array
выполнится или отклонится, вonFulfilled
мы получим результат первого такого промиса.
allSettled - нужны все завершенные
дожидаемся пока все промисы из
array
будут завершены, вonFulfilled
мы получаем массив результатов в том же порядке в каком были установлены промисы в начальном массиве.
all | any | race | allSettled | |
если аргумент пустой массив | fulfilled | rejected | pending | fulfilled |
становится fulfilled | все resolved | один resolved | один resolved | все resolved |
возвращает в коллбэк в случае fulfilled | все resolved | первый resolved | первый resolved | все resolved |
Пояснение: метод all
Если в метод all передать пустой массив
Promise.all([])
, то возвращаемый методом all промис становится fulfilled так как у него нет ни одного rejected промиса.Если в метод all передать массив с промисами
Promise.all([,,,])
, то возвращаемый методом all промис становится fulfilled в двух случаях: если все промисы в массиве будут resolved или хотя бы один будет rejected.Если возвращаемый методом all промис становится fulfilled то в соответствующий коллбэк отправляется массив данных от всех resolved промисов или данные от одного rejected промиса.
Пояснение: метод any
Если в метод any передать пустой массив
Promise.any([])
, то возвращаемый методом any промис становится rejected так как у него нет ни одного fulfilled промиса.Если в метод any передать массив с промисами
Promise.any([,,,])
, то возвращаемый методом any промис становится fulfilled в двух случаях: если хотя бы один будет resolved или все промисы в массиве будут rejected.Если возвращаемый методом any промис становится fulfilled то в соответствующий коллбэк отправляется данные от первого resolved промиса или AggregateError так ни один промис не закончился успешно.
Пояснение: метод race
Если в метод race передать пустой массив
Promise.race([])
, то возвращаемый методом race промис остается pending так как у него нет ни одного fulfilled промиса.Если в метод race передать массив с промисами
Promise.race([,,,])
, то возвращаемый методом race промис остается pending до тех пор пока хотя бы один промис в массиве не станет resolved или rejected.Если возвращаемый методом race промис становится fulfilled то в соответствующий коллбэк отправляется данные от первого resolved или первого rejected промиса.
Пояснение: метод allSettled
Если в метод allSettled передать пустой массив
Promise.allSettled([])
, то возвращаемый методом allSettled промис становится fulfilled.Если в метод allSettled передать массив с промисами
Promise.allSettled([,,,])
, то возвращаемый методом allSettled промис становится fulfilled в случае: если все промисы в массиве будут settled.Если возвращаемый методом allSettled промис становится fulfilled то в соответствующий коллбэк отправляется массив данных от всех settled промисов.