Перейти к основному содержимому

promises

Промис​

Промис хранит результат операции, который появится позже. У него три состояния: pending (ещё нет результата), fulfilled (есть значение) и rejected (есть ошибка).

resolve и reject — это функции, а не состояния. Срабатывает только первый вызов: повторный resolve или reject ничего не меняет.

Promise

const promise = new Promise((resolve, reject) => {
const ok = true;

if (ok) {
resolve('done');
} else {
reject(new Error('failed'));
}
});

promise.then(value => console.log(value)).catch(error => console.log(error));

then получает значение и возвращает новый промис. catch получает отказ. Цепочка и отличие catch от finally разобраны в заметке then-catch-finally.

Уже готовое значение​

Promise.resolve сразу создаёт успешный промис, Promise.reject — отклонённый.

Promise.resolve(1).then(value => console.log(value)); // 1

Promise.reject(new Error('failed')).catch(error => console.log(error.message));

Таймер​

Промис завершают внутри исполнителя, когда асинхронная операция закончилась.

const delay = ms => {
return new Promise(resolve => {
setTimeout(() => resolve('done'), ms);
});
};

delay(1000).then(value => console.log(value));

Событие​

Тот же приём подходит для события. Наружу отдают функцию, которая возвращает промис.

const loadScript = src => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');

script.src = src;
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Ошибка загрузки ${src}`));

document.head.append(script);
});
};

loadScript(
'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js',
)
.then(script => {
console.log(script.src);
return script;
})
.then(script => console.log('ещё один обработчик', script.src))
.catch(error => console.log(error.message));

Без return второй then получит undefined. Один промис можно подписать несколькими отдельными then: каждый получит одно и то же значение.

Несколько промисов​

Promise.all ждёт все и сохраняет порядок результатов. Если один отклонится, весь результат отклонится.

Promise.all()

Promise.all([loadPlanet(), loadPosts()]).then(([planet, posts]) => {
console.log(planet, posts);
});

Promise.allSettled дожидается всех, включая ошибки. У каждого пункта есть status: fulfilled или rejected.

Promise.allSettled()

Promise.allSettled([loadPlanet(), loadPosts()]).then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log(result.value);
} else {
console.log(result.reason);
}
});
});

Promise.race завершается первым успешным или первым отказом. Promise.any завершается первым успехом и отклоняется, только если отказали все.

Promise.race()

Promise.any()