В этом руководстве вы узнаете, как использовать метод JavaScript Promise.any()
для создания промисов.
Метод Promise.any()
принимает список объектов Promise как итерируемый объект:
Promise.any(iterable);
Если одно из обещаний в итерируемом объекте выполнено, Promise.any()
возвращает одно обещание, которое разрешается в значение, являющееся результатом выполненного обещания:
На этой диаграмме:
promise1
в значениеv1
в момент времениt1
.promise2
преобразуется в значениеv2
вt2
.Promise.any()
возвращает обещание, которое преобразуется в значениеv1
, являющееся результатомpromise1
, в момент времениt1
.
Promise.any()
возвращает промис, который выполняется с любым первым выполненным обещанием, даже если некоторые промисы в итерируемом объекте отклонены:
На этой диаграмме:
promise1
отклонено сerror
в момент времениt1
.promise2
выполняется до значенияv2
вt2
.Promise.any()
возвращает обещание, которое преобразуется в значениеv2
, являющееся результатомpromise2
. Обратите внимание, что методPromise.any()
игнорирует отклоненное обещание(promise1
).
Если все промисы в итерируемом объекте отклонены или если итерируемый объект пуст, Promise.any()
возвращает промис, который отклоняется с AggregateError
, содержащим все причины отклонения. AggregateError
является подклассом Error
.
На этой диаграмме:
promise1
отклонено из-заerror1
в момент времениt1
.error2
promise2
момент времениt2
.Promise.any()
возвращает обещание, которое было отклонено в момент времениt2
, сAggregateError
, содержащимerror1
иerror2
всех отклоненных обещаний.
Примеры использования
Давайте рассмотрим несколько примеров использования Promise.any()
.
1) Пример выполнения всех промисов
В следующем примере демонстрируется метод Promise.any()
со всеми выполненными промисами:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { console.log('Promise 1 fulfilled'); resolve(1); }, 1000); }); const p2 = new Promise((resolve, reject) => { setTimeout(() => { console.log('Promise 2 fulfilled'); resolve(2); }, 2000); }); const p = Promise.any([p1, p2]); p.then((value) => { console.log('Returned Promise'); console.log(value); });
Выход:
Promise 1 fulfilled Returned Promise 1 Promise 2 fulfilled
Как это работает:
- Во-первых, создайте новое обещание
p1
, которое будет разрешаться в значение1
через одну секунду. - Во-вторых, создайте новое обещание
p2
, которое через две секунды преобразуется в значение2
. - В-третьих, используйте метод
Promise.any()
, который использует два промисаp1
иp2
.Promise.any()
возвращает обещаниеp
, которое будет преобразовано в значение1
первого выполненного обещания(p1
) через одну секунду.
2) Пример отклонения одного обещания
В следующем примере используется метод Promise.any()
со списком промисов с отклоненным промисом:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { console.log('Promise 1 rejected'); reject('error'); }, 1000); }); const p2 = new Promise((resolve, reject) => { setTimeout(() => { console.log('Promise 2 fulfilled'); resolve(2); }, 2000); }); const p = Promise.any([p1, p2]); p.then((value) => { console.log('Returned Promise'); console.log(value); });
Выход:
Promise 1 rejected Promise 2 fulfilled Returned Promise 2
В этом примере Promise.any()
игнорирует отклоненное обещание. Когда p2
разрешается со значением 2
, Promise.any()
возвращает обещание, которое разрешается в то же значение, что и результат p2
.
3) Пример отказа от всех промисов
В следующем примере показано, как использовать метод Promise.any()
при отклонении всех промисов:
const p1 = new Promise((resolve, reject) => { setTimeout(() => { console.log('Promise 1 rejected'); reject('error1'); }, 1000); }); const p2 = new Promise((resolve, reject) => { setTimeout(() => { console.log('Promise 2 rejected'); reject('error2'); }, 2000); }); const p = Promise.any([p1, p2]); p.catch((e) => { console.log('Returned Promise'); console.log(e, e.errors); });
Выход:
Promise 1 rejected Promise 2 rejected Returned Promise [AggregateError: All promises were rejected] [ 'error1', 'error2' ]
В этом примере и p1
, и p2
были отклонены со строками error1
и error2
. Таким образом, метод Promise.any()
был отклонен с объектом AggregateError
, у которого есть свойство errors
, содержащее все ошибки отклоненных промисов.
Когда использовать?
На практике Promise.any()
используется для возврата первого выполненного промиса. Как только обещание выполнено, метод не ожидает завершения других обещаний.
Например, у вас есть ресурс, обслуживаемый двумя или более сетями доставки контента(CDN). Чтобы динамически загрузить первый доступный ресурс, вы можете использовать метод Promise.any()
.
В следующем примере метод Promise.any()
используется для получения двух изображений и отображения первого доступного изображения.
Файл index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>JavaScript Promise.any() Demo</title> </head> <body> <script src="js/app.js"></script> </body> </html>
Файл app.js
function getImageBlob(url) { return fetch(url).then((response) => { if (!response.ok) { throw new Error(`HTTP status: ${response.status}`); } return response.blob(); }); } let cat = getImageBlob( 'https://upload.wikimedia.org/wikipedia/commons/4/43/Siberian_black_tabby_blotched_cat_03.jpg' ); let dog = getImageBlob( 'https://upload.wikimedia.org/wikipedia/commons/a/af/Golden_retriever_eating_pigs_foot.jpg' ); Promise.any([cat, dog]) .then((data) => { let objectURL = URL.createObjectURL(data); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); }) .catch((e) => { console.log(e.message); });
Как это работает:
- Во-первых, определите функцию
getImageBlob()
, которая использует API выборки для получения большого двоичного объекта изображения из URL-адреса.getImageBlob()
возвращает объектPromise
, который разрешается в большой двоичный объект изображения. - Во-вторых, определите два обещания, которые загружают изображения.
- В-третьих, покажите первое доступное изображение с помощью
Promise.any().