Výjimky v řetězcích promises v JavaScriptu

Nechť z nějakého důvodu naše promise skončí chybou:

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

V tomto případě se provádění kódu okamžitě přesune k tomu then, ve kterém je funkce pro zpracování chyby, nebo k prvnímu catch, podle toho, co se objeví dříve.

Zde je příklad první situace:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  },
  function(error) {
    // provádění se okamžitě přesune sem
  }
).then(
  function(result) {
    console.log(result);
  }
);

Zde je příklad druhé situace:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // provádění se okamžitě přesune sem
  }
).then(
  function(result) {
    console.log(result);
  }
);

Funkce pro zpracování má dvě možnosti akce: pokud se vyrovnala s výjimečnou situací, může vrátit výsledek pomocí return a provádění bude pokračovat dále po řetězci. Pokud se nevyrovnala s chybou, pak může buď nic nevracet, nebo vyhodit výjimku pomocí throw. V tomto případě se provádění přesune k dalšímu zachytávači chyby (v then nebo catch - cokoli se objeví dříve).

Zpravidla jsou všechny chyby řetězce zachyceny na jednom místě: na konci řetězce je umístěn catch:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // dostaneme se sem v případě chyby
  }
);

Přičemž výjimka může vzniknout v samotné promise, nebo být vyhozena pomocí throw v jakémkoli článku řetězce:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    if (všeDobře) {
      return result + '2';
    } else {
      throw new Error('chyba'); // přecházíme k nejbližšímu zachytávači
    }
  }
)
.then(
  function(result) {
    return result + '3';
  }
).catch(
  function(error) {
    // nejbližší zachytávač
  }
);

Mějte na paměti, že catch je potřebný právě pro diagnostiku chyby: je řešitelná nebo ne. Pokud je chyba řešitelná, pak catch by měl předat její řešení následujícímu za sebou then. A pokud není řešitelná (nebo daný catch prostě neví, jak ji vyřešit), pak musíme buď nic nevracet, nebo vyhodit výjimku:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    if (chybaŘešitelná) {
      return 'data'; // odesíláme na další then
    } else {
      // nic nevracíme nebo vyhazujeme výjimku
    }
  }
).then(
  function(result) {
    // zde řešíme chybu
  }
);