Page 242 - Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017
P. 242
Одно из преимуществ сцепления обязательств в том, что вы не обязаны обраба
тывать ошибки на каждом этапе; если где-нибудь в цепочке произойдет ошибка, то
цепочка остановится и управление перейдет к обработчику catch. Давайте заменим
1
обратный отсчет 5 -секундным суеверным обратным отсчетом; вы обнаружите, что
функция launch никогда не будет вызвана.
Предотвращение незавер ш е н н ых обязательств
Обязательства могут упростить ваш асинхронный код и защитить вас от проблем
функций обратных вызовов, вызываемых несколько раз, но они не защищают вас
от проблемы обязательств, которые никогда не завершаются ( т.е. когда вы забываете
вызвать resol ve или rej ect). Ошибки этого вида может быть очень трудно обнару
жить, поскольку никакой ошибки нет . . а в сложной системе незавершенное обяза
.
тельство может быть просто потеряно.
Один из способов предотвращения этого заключается в определении периода
для обязательств; если обязательство не завершено за некий разумный период вре
мени, оно автоматически отклоняется. Вполне очевидно, что это вам решать, каков
"разумный период времени''. Если у вас достаточно сложный алгоритм, выполнение
которого предположительно займет 10 минут, не устанавливайте 1 - секундный период.
Давайте вставим в нашу функцию launch искусственный отказ. Скажем, наша ра
кета очень экспериментальная, и она отказывает приблизительно в половине случаев.
function launch { ) {
return new Promise { function ( r esolve, rej ect ) {
i f {Math . random { ) < 0 . 5 ) return ; / / отказ ракеты
console . l og { " П oexaл ! " ) ;
и
setTimeout { function ) {
{
resolve { " Ha орбите ! " ) ;
} , 2 * 1 0 0 0 ) ; / / действительно очень быстрая ракета
} ) ;
Способ отказа в данном примере не очень достойный: мы не вызываем функцию
rej ect и даже ничего не выводим на консоль. Мы просто тихо выходим в половине
случаев. Если запустить этот пример несколько раз, то можно увидеть, что иногда он
срабатывает, а иногда нет". безо всякого сообщения об ошибке, что явно нежелательно.
Мы можем написать функцию, которая задает обязательству период.
function addTimeout { f n, t i meout ) {
i f { t i meout === undefined) t i meout = 1 0 0 0 ; / / стандартный период
return function { . . . args ) {
return new Promise { function ( r e solve , rej ect ) {
const tid = setTimeout { r ej ect, timeout ,
new Еrrоr { "Истек период обязательства " ) ) ;
fn { . . . ar s )
g
Обязательства 245

