В этом руководстве вы узнаете, как использовать метод 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.error2promise2момент времени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().
