Выключэнні ў ланцужках промісаў у JavaScript

Хай па якіхсьці прычынах наш проміс завяршыцца з памылкай:

javascriptlet promise = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject('error');
  }, 3000);
});

У гэтым выпадку выкананне коду адразу перайдзе да таго then, у якім ёсць функцыя-апрацоўшчык памылкі, альбо ў першы catch, глядзі што сустрэнецца раней.

Вось прыклад першай сітуацыі:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  },
  function(error) {
    // выкананне адразу перайдзе сюды
  }
).then(
  function(result) {
    console.log(result);
  }
);

Вось прыклад другой сітуацыі:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // выкананне адразу перайдзе сюды
  }
).then(
  function(result) {
    console.log(result);
  }
);

Функцыя-апрацоўшчык мае два варыянты дзеянняў: калі яна справілася з выключнай сітуацыяй, то можа вярнуць вынік праз return і выкананне працягнецца далей па ланцужку. Калі ж яна не справілася з памылкай, то можа альбо нічога не вяртаць, альбо выкінуць выключэнне праз throw. У гэтым выпадку выкананне перайдзе да наступнага перахопніка памылкі (у then альбо catch - што сустрэнецца раней).

Як правіла, усе памылкі ланцужка перахопліваюцца ў адным месцы: у канцы ланцужка размяшчаецца catch:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // трапім сюды ў выпадку памылкі
  }
);

Пры гэтым выключэнне можа ўзнікнуць у самым промісе, альбо выкінута праз throw у любым звяне ланцужка:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    if (усёДобра) {
      return result + '2';
    } else {
      throw new Error('памылка'); // пераходзім да бліжэйшага перахопніка
    }
  }
)
.then(
  function(result) {
    return result + '3';
  }
).catch(
  function(error) {
    // бліжэйшы перахопнік
  }
);

Улічвайце, што catch патрэбны менавіта для дыягностыкі памылкі: яна вырашальная альбо не. Калі памылка вырашальная, то catch павінен перадаць яе рашэнне наступнаму за сабой then. А калі не вырашальная (альбо дадзены catch проста не ведае як яе вырашыць), то мы павінны альбо нічога не вярнуць альбо кінуць выключэнне:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    if (памылкаВырашальная) {
      return 'дадзеныя'; // адпраўляем на наступны then
    } else {
      // нічога не вяртаем альбо кідаем выключэнне
    }
  }
).then(
  function(result) {
    // тут вырашаем памылку
  }
);