Promise Flashcards
what is promise chaining
Promise chaining is a syntax that allows you to chain together multiple asynchronous tasks in a specific order. This is great for complex code where one asynchronous task needs to be performed after the completion of a different asynchronous task
Идея состоит в том, что результат первого промиса передаётся по цепочке обработчиков .then.
- Начальный промис успешно выполняется через 1 секунду (*),
- Затем вызывается обработчик в .then (**).
- Возвращаемое им значение передаётся дальше в следующий обработчик .then (***)
результат выполнения кода?
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
});
promise.then(function(result) {
alert(result);
return result * 2;
});
promise.then(function(result) {
alert(result);
return result * 2;
});
1
Поток выполнения такой:
Начальный промис успешно выполняется через 1 секунду (*)
what is promise in js?
Можно ли “перевыполнить” промис?
Что выведет код ниже?
let promise = new Promise(function(resolve, reject) { resolve(1);
setTimeout(() => resolve(2), 1000);
});
promise.then(alert);
решение
Вывод будет: 1.
Второй вызов resolve будет проигнорирован, поскольку учитывается только первый вызов reject/resolve. Все последующие вызовы – игнорируются.
Встроенная функция setTimeout использует колбэк-функции. Создайте альтернативу, использующую промисы.
function delay(ms) { // ваш код }
delay(3000).then(() => alert(‘выполнилось через 3 секунды’));
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
delay(3000).then(() => alert(‘выполнилось через 3 секунды’));
Заметьте, что resolve вызывается без аргументов. Мы не возвращаем из delay ничего, просто гарантируем задержку.
для чего используется catch
Цепочки промисов отлично подходят для перехвата ошибок. Если промис завершается с ошибкой, то управление переходит в ближайший обработчик ошибок. На практике это очень удобно.
Например, для fetch указана неправильная ссылка (сайт не существует), и .catch перехватывает ошибку:
fetch(‘https://no-such-server.blabla’) // ошибка
.then(response => response.json())
.catch(err => alert(err)) // TypeError: failed to fetch (текст может отличаться)
Как видно, .catch не обязательно должен быть сразу после ошибки, он может быть далее, после одного или даже нескольких .then
Или, может быть, с сервером всё в порядке, но в ответе мы получим некорректный JSON. Самый лёгкий путь перехватить все ошибки – это добавить .catch в конец цепочки
Что происходит, когда обычная ошибка не перехвачена try..catch? И в случае необработанной ошибки промиса.
Скрипт умирает с сообщением в консоли.
JavaScript-движок отслеживает такие ситуации и генерирует в этом случае глобальную ошибку. Вы можете увидеть её в консоли.
Promise Methods. What is Promise.all?
Promise.all
Допустим, нам нужно запустить множество промисов параллельно и дождаться, пока все они выполнятся.
Например, параллельно загрузить несколько файлов и обработать результат, когда он готов.
Для этого как раз и пригодится Promise.all.
let promise = Promise.all(iterable); Метод Promise.all принимает массив промисов (может принимать любой перебираемый объект, но обычно используется массив) и возвращает новый промис.
Новый промис завершится, когда завершится весь переданный список промисов, и его результатом будет массив их результатов.
Promise Methods Если любой из промисов в Promise.All завершится с ошибкой что будет дальше?
Если один промис завершается с ошибкой, то весь Promise.all завершается с ней, полностью забывая про остальные промисы в списке. Их результаты игнорируются.
Например, если сделано несколько вызовов fetch, как в примере выше, и один не прошёл, то остальные будут всё ещё выполняться, но Promise.all за ними уже не смотрит. Скорее всего, они так или иначе завершатся, но их результаты будут проигнорированы.
*Promise Methods What is Promise.allSettled
Cинтаксис:
let promise = Promise.allSettled(iterable); Promise.all завершается с ошибкой, если она возникает в любом из переданных промисов. Это подходит для ситуаций «всё или ничего», когда нам нужны все результаты для продолжения:
Метод Promise.allSettled всегда ждёт завершения всех промисов. В массиве результатов будет
{status:”fulfilled”, value:результат} для успешных завершений,
{status:”rejected”, reason:ошибка} для ошибок.
Например, мы хотели бы загрузить информацию о множестве пользователей. Даже если в каком-то запросе ошибка, нас всё равно интересуют остальные.
Promise methods Что такое Полифил?
Если браузер не поддерживает Promise.allSettled, для него легко сделать полифил:
if(!Promise.allSettled) { Promise.allSettled = function(promises) { return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({ status: 'fulfilled', value: value }), error => ({ status: 'rejected', reason: error })))); }; }
Promise Methods Promise.race
Метод очень похож на Promise.all, но ждёт только первый выполненный промис, из которого берёт результат (или ошибку).
Синтаксис:
let promise = Promise.race(iterable); Например, тут результат будет 1:
Promise.race([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error(“Ошибка!”)), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert); // 1
Быстрее всех выполнился первый промис, он и дал результат. После этого остальные промисы игнорируются.
Promise Methods resolve/reject
Promise.resolve(value) создаёт успешно выполненный промис с результатом value.
Promise.reject(error) создаёт промис, завершённый с ошибкой error.
- что такое Промисификация ?
Эта функция-обёртка возвращает промис и передаёт вызов оригинальной f, отслеживая результат в своём колбэке:
Обработчики промисов .then/.catch/.finally всегда асинхронны?
да
что будет в результате выполнения, почему?
let promise = Promise.resolve();
promise.then(() => alert(“промис выполнен”));
alert(“код выполнен”);
сначала код выполнен, а потом промис выполнен.
Асинхронные задачи требуют правильного управления. Для этого стандарт предусматривает внутреннюю очередь PromiseJobs, более известную как «очередь микрозадач (microtask queue)» (термин V8).
Как сказано в спецификации:
Очередь определяется как первым-пришёл-первым-ушёл (FIFO): задачи, попавшие в очередь первыми, выполняются тоже первыми.
Выполнение задачи происходит только в том случае, если ничего больше не запущено.
Или, проще говоря, когда промис выполнен, его обработчики .then/catch/finally попадают в очередь. Они пока не выполняются. Движок JavaScript берёт задачу из очереди и выполняет её, когда он освободится от выполнения текущего кода.
Вот почему сообщение «код выполнен» в примере выше будет показано первым.