Кратко
СкопированоМетод any
— один из статических методов объекта Promise
. Его используют, когда нужно запустить несколько промисов параллельно и дождаться первого успешного разрешённого.
Как пишется
СкопированоPromise
принимает итерируемую коллекцию промисов, чаще всего — массив. Метод возвращает новый промис, который выполнится, когда выполнится первый из промисов, переданных в виде перечисляемого аргумента. Промис может быть отклонён, если все из переданных промисов завершатся с ошибкой.
Возвращает значение первого успешно выполнившегося промиса.
Как понять
СкопированоМетод полезен, когда нужно вернуть первый исполненный промис. После того как один из промисов будет исполнен, метод не будет дожидаться исполнения остальных.
В отличие от Promise
, который содержит массив значений исполненных промисов, Promise
содержит только одно значение при условии, что хотя бы один из промисов исполнен успешно. Такой подход полезен, когда нужно, чтобы выполнился только один промис, неважно какой.
Также Promise
отличается от Promise
. Метод Promise
возвращает промис, содержащий значение первого завершённого (resolved
или rejected
). Метод Promise
возвращает промис, содержащий значение первого успешно выполненного (resolved
) промиса. Promise
проигнорирует исполнение промисов с ошибкой (rejection
) до первого исполненного успешного (resolved
).
Можете использовать Promise
, когда есть две картинки и надо отобразить ту, которая загрузится быстрее:
function fetchAndDecode(url) { return fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } else { return response.blob() } })}const coffee = fetchAndDecode('coffee.jpg')const tea = fetchAndDecode('tea.jpg')Promise.any([coffee, tea]) .then((value) => { const objectURL = URL.createObjectURL(value) const image = document.createElement('img') image.src = objectURL document.body.appendChild(image) }) .catch((error) => { console.error(error) })
function fetchAndDecode(url) { return fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } else { return response.blob() } }) } const coffee = fetchAndDecode('coffee.jpg') const tea = fetchAndDecode('tea.jpg') Promise.any([coffee, tea]) .then((value) => { const objectURL = URL.createObjectURL(value) const image = document.createElement('img') image.src = objectURL document.body.appendChild(image) }) .catch((error) => { console.error(error) })
Успешное выполнение нескольких промисов. Создадим два промиса, второй выполнится раньше:
const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 1000))
const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 5000)) const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 1000))
Передадим массив из созданных промисов в Promise
:
Promise.any([promise1, promise2]) .then((result) => { console.log(result) })// 2
Promise.any([promise1, promise2]) .then((result) => { console.log(result) }) // 2
Пустой массив промисов. Передадим пустой массив в Promise
:
Promise.any([]) .then((result) => { console.log(result) }) .catch(error => { console.error(error) })
Promise.any([]) .then((result) => { console.log(result) }) .catch(error => { console.error(error) })
В итоге обработчик then
будет проигнорирован, и будет выполняться код из обработчика ошибок catch
.
Один из промисов завершился ошибкой. Метод Promise
не завершится с ошибкой, если хотя бы один из промисов выполнится успешно.
В примере промис promise2
завершается с ошибкой:
const promise1 = new Promise( resolve => setTimeout(() => resolve(1), 5000))const promise2 = new Promise( (resolve, reject) => setTimeout(() => reject('error'), 1000))Promise.any([promise1, promise2]) .then((result) => { console.log(result) // 1 }) .catch(error => { console.error(error) })
const promise1 = new Promise( resolve => setTimeout(() => resolve(1), 5000) ) const promise2 = new Promise( (resolve, reject) => setTimeout(() => reject('error'), 1000) ) Promise.any([promise1, promise2]) .then((result) => { console.log(result) // 1 }) .catch(error => { console.error(error) })
В итоге обработчик catch
проигнорируется и выполнится код из обработчика then
со значением 1
в переменной result
.
Все промисы завершились ошибкой. Метод Promise
завершится с ошибкой, если все переданные промисы завершатся с ошибкой.
const promise1 = new Promise( (resolve, reject) => setTimeout(() => reject('error1'), 5000))const promise2 = new Promise( (resolve, reject) => setTimeout(() => reject('error2'), 1000))Promise.any([promise1, promise2]) .then((result) => { console.log(result) }) .catch(error => { console.error(error) // AggregateError: All promises were rejected console.log(error.errors) // ['error1', 'error2'] })
const promise1 = new Promise( (resolve, reject) => setTimeout(() => reject('error1'), 5000) ) const promise2 = new Promise( (resolve, reject) => setTimeout(() => reject('error2'), 1000) ) Promise.any([promise1, promise2]) .then((result) => { console.log(result) }) .catch(error => { console.error(error) // AggregateError: All promises were rejected console.log(error.errors) // ['error1', 'error2'] })
В итоге обработчик then
проигнорируется и выполнится код из обработчика ошибок catch
. В этом случае error
это экземпляр класса Aggregate
. Объект Aggregate
содержит ошибки от обоих промисов в массиве errors
.
☝️ Порядок в массиве ошибок определяется очерёдностью промисов в исходной коллекции.
Непромисы в массиве промисов. Если в Promise
передать что-то помимо промисов, метод вернёт промис, содержащий первый переданный аргумент любого типа как результат выполнения. Под капотом при этом произойдёт его преобразование с помощью метода Promise
.
Передадим в Promise
массив значений, которые не являются промисами:
const number = 2const obj = {key: 'value'}const func = () => trueconst bool = falseconst nulled = nullconst undef = undefinedPromise.any([number, obj, func, bool, nulled, undef]) .then((result) => { console.log(result) // 2 })Promise.any([obj, func, bool, nulled, undef, number]) .then((result) => { console.log(result) // {key: 'value'} })Promise.any([func, bool, nulled, undef, number, obj]) .then((result) => { console.log(result) // () => true })Promise.any([bool, nulled, undef, number, obj, func]) .then((result) => { console.log(result) // false })Promise.any([nulled, undef, number, obj, func, bool]) .then((result) => { console.log(result) // null })Promise.any([undef, number, obj, func, bool, nulled]) .then((result) => { console.log(result) // undefined })
const number = 2 const obj = {key: 'value'} const func = () => true const bool = false const nulled = null const undef = undefined Promise.any([number, obj, func, bool, nulled, undef]) .then((result) => { console.log(result) // 2 }) Promise.any([obj, func, bool, nulled, undef, number]) .then((result) => { console.log(result) // {key: 'value'} }) Promise.any([func, bool, nulled, undef, number, obj]) .then((result) => { console.log(result) // () => true }) Promise.any([bool, nulled, undef, number, obj, func]) .then((result) => { console.log(result) // false }) Promise.any([nulled, undef, number, obj, func, bool]) .then((result) => { console.log(result) // null }) Promise.any([undef, number, obj, func, bool, nulled]) .then((result) => { console.log(result) // undefined })