Автор заметки, перевод которой мы сегодня публикуем, говорит, что с трудом удержался от того, чтобы не назвать её «Finally — возможность, которую все ждали», или как-то пошутить на эту тему. В итоге он решил обойтись без шуток и просто рассказать о по-настоящему важной и полезной возможности объектов Promise.
![](https://habrastorage.org/webt/vx/we/c2/vxwec2slp-mndo8ep4anvgcykgg.png)
Если вы только начинаете осваивать JavaScript и не слишком хорошо знакомы с промисами (иногда их называют «обещаниями», «обещанными результатами», «Promise-объектами»), то, возможно, вам будут интересны наши предыдущие публикации на эту тему:
> Промисы в ES6: паттерны и анти-паттерны
> JavaScript: методы асинхронного программирования
> JavaScript ES8 и переход на async / await
> Async/await: 6 причин забыть о промисах
> Побег из ада async/await
> JavaScript ES6: пишем меньше — делаем больше
> Руководство по промисам для тех, кто хочет в них разобраться
> Конструкция async/await в JavaScript: сильные стороны, подводные камни и особенности использования
> Использование промисов в JavaScript
Методу
Метод промисов
Рассмотрим пример:
Это — совершенно обычный промис, который разрешается через 2000 миллисекунд. Если после этого нужно выполнить какое-то действие — нам понадобится блок
Методу
Независимо от того, как промис завершит работу, в консоль, помимо соответствующего сообщения, будет выведен текст
То, что в ES2018 появился метод
В каких ситуациях может пригодиться метод
Уважаемые читатели! Пользовались ли вы заменителями метода промисов finally до появления его стандартных реализаций?
![](https://habrastorage.org/webt/vx/we/c2/vxwec2slp-mndo8ep4anvgcykgg.png)
Если вы только начинаете осваивать JavaScript и не слишком хорошо знакомы с промисами (иногда их называют «обещаниями», «обещанными результатами», «Promise-объектами»), то, возможно, вам будут интересны наши предыдущие публикации на эту тему:
> Промисы в ES6: паттерны и анти-паттерны
> JavaScript: методы асинхронного программирования
> JavaScript ES8 и переход на async / await
> Async/await: 6 причин забыть о промисах
> Побег из ада async/await
> JavaScript ES6: пишем меньше — делаем больше
> Руководство по промисам для тех, кто хочет в них разобраться
> Конструкция async/await в JavaScript: сильные стороны, подводные камни и особенности использования
> Использование промисов в JavaScript
Метод Promise.prototype.finally
Методу
Promise.prototype.finally
посвящён пункт 25.6.5.3 стандарта ECMAScript 2018. По информации ресурса caniuse.com, уровень поддержки этого метода составляет примерно 81%. Этим методом можно пользоваться и в среде Node.js.Метод промисов
finally
— это одно из важнейших новшеств стандарта, которое позволяет задавать функцию, которая будет выполнена независимо от результата промиса. Такая функция выполнится и при успешном разрешении промиса и при его отклонении. Рассмотрим пример:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => { resolve('success!!!'); }, 2000);
});
Это — совершенно обычный промис, который разрешается через 2000 миллисекунд. Если после этого нужно выполнить какое-то действие — нам понадобится блок
then
:myPromise.then(
result => { console.log(result) },
failMessage => { console.log(failMessage) }
);
Методу
then
переданы две анонимных функции. Первая будет выполнена в том случае, если промис будет успешно разрешён. Вторая — при его отклонении. Наш промис всегда завершает работу успешно, в консоль всегда будет выводиться сообщение success!!!
. Всё это очень хорошо, но как быть, если надо, чтобы некие действия выполнялись бы и после отклонения промиса, и после успешного завершения его работы? Тут нам и поможет метод finally
:const myPromise = new Promise((resolve, reject) => {
setTimeout(() => { resolve('success!!!'); }, 2000);
});
myPromise.then(
result => { console.log(result) },
failMessage => { console.log(failMessage) }
).finally(finallyMessage => { console.log('FINALLY!!')});
Независимо от того, как промис завершит работу, в консоль, помимо соответствующего сообщения, будет выведен текст
FINALLY!!
, что говорит нам о том, что функция обратного вызова, переданная методу finally
, срабатывает в любом случае. Для того чтобы в этом убедиться — можете поэкспериментировать.Итоги
То, что в ES2018 появился метод
Promise.prototype.finally
, говорит о том, что в обозримом будущем можно ожидать очень высокого уровня его поддержки браузерами. Это значит, что то, для чего раньше приходилось использовать вспомогательные инструменты, созданные сторонними разработчиками, теперь может быть реализовано стандартными средствами.В каких ситуациях может пригодиться метод
Promise.prototype.finally
? Например — если при запуске промиса, используемого для загрузки чего-либо, начинает воспроизводиться некая анимация, в finally
можно завершить эту анимацию. В блоке finally
можно, например, закрыть некое модальное окно. На самом деле, существует множество ситуаций, в которых метод finally
может оказаться полезным.Уважаемые читатели! Пользовались ли вы заменителями метода промисов finally до появления его стандартных реализаций?
![](https://habrastorage.org/files/1ba/550/d25/1ba550d25e8846ce8805de564da6aa63.png)
Комментарии (12)
agentx001
24.10.2018 17:09Промисы прекрасны. Но вот раздражает, что нельзя завершить работу где-то в середине цепочки как-то кроме выбрасывания исключения.
mayorovp
24.10.2018 19:11А откуда такое требование — "как-то кроме выбрасывания исключения"? Чем исключение не устроило?
Или смущает не исключение, а сама операция
throw
? В таком случаеreturn Promise.reject(...)
в помощь.
Staltec
24.10.2018 20:31+2Лучше бы реализовали Promise.prototype.cancel() который реализован в том же Bluebird. Очень полезен в случаях когда установка стейта react-компонента уже неактуальна потому как компонент успел размонтироваться пока промис исполнялся.
mayorovp
26.10.2018 08:39Вот только в том же Bluebird один раз уже пришлось менять семантику отмены. И все равно остались странности, из-за которых отмена обещаний и выключена по умолчанию.
Odrin
25.10.2018 17:04+1одно из важнейших новшеств стандарта
Которое было еще во времена jQuery Deferred и Q ($q из первого angular). Для меня до сих пор остается загадкой, почему finally не вошел в стандарт с самого начала, ведь это удобная и сама-собой напрашивающаяся функция.
ZLBRSTN
Promise.then(...).catch(...).then(/* Не то же самое? */)
mayorovp
Конкретно в приведенном случае- да, то же самое. Потому что значение промиса нигде не используется. А вот если оно используется, то так красиво сделать не получится. Попробуйте заменить вот это:
rzcoder
Не то же самое. catch тоже может кинуть экцепшн и тогда then не сработает.