Përjashtimet në zinxhirët e premtimeve në JavaScript

Le të supozojmë se për disa arsye premtimi ynë përfundon me një gabim:

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

Në këtë rast, ekzekutimi i kodit do të kalojë menjëherë te ai then në të cilin ka një funksion trajtues gabimesh, ose te catch i parë, varësisht se cili haset më parë.

Ja një shembull të situatës së parë:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  },
  function(error) {
    // ekzekutimi do të kalojë menjëherë këtu
  }
).then(
  function(result) {
    console.log(result);
  }
);

Ja një shembull të situatës së dytë:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // ekzekutimi do të kalojë menjëherë këtu
  }
).then(
  function(result) {
    console.log(result);
  }
);

Funksioni trajtues ka dy mundësi veprimi: nëse e ka trajtuar situatën e përjashtimit, mund të kthejë rezultatin përmes return dhe ekzekutimi do të vazhdojë më tej përgjatë zinxhirit. Nëse nuk e ka trajtuar gabimin, mund ose të mos kthejë asgjë, ose të hedhë një përjashtim përmes throw. Në këtë rast, ekzekutimi do të kalojë te kapësi tjetër i gabimeve (në then ose catch - çfarëdo që të haset më parë).

Zakonisht, të gjitha gabimet e zinxhirit kapen në një vend: në fund të zinxhirit vendoset një catch:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // do të vijmë këtu në rast gabimi
  }
);

Në këtë rast, përjashtimi mund të lindë në vetë premtimin, ose të hidhet përmes throw në çdo lidhje të zinxhirit:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    if (gjithçkaMirë) {
      return result + '2';
    } else {
      throw new Error('gabim'); // kalojmë te kapësi më i afërt
    }
  }
)
.then(
  function(result) {
    return result + '3';
  }
).catch(
  function(error) {
    // kapësi më i afërt
  }
);

Kini parasysh që catch nevojitet pikërisht për diagnostikimin e gabimit: a është i zgjidhshëm apo jo. Nëse gabimi është i zgjidhshëm, atëherë catch duhet t'ia kalojë zgjidhjen then pas vetes. Por nëse nuk është i zgjidhshëm (ose ky catch thjesht nuk di si ta zgjidhë atë), atëherë duhet ose të mos kthejmë asgjë ose të hedhim një përjashtim:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    if (gabimiIZgjidhshëm) {
      return 'të dhënat'; // dërgojmë te then-i pasardhës
    } else {
      // nuk kthejmë asgjë ose hedhim përjashtim
    }
  }
).then(
  function(result) {
    // këtu zgjidhim gabimin
  }
);