A promise hell problémája a JavaScriptben

Már tudod, hogy a promise-okat azért hozták létre, hogy megoldják a callback hell problémáját. Azonban idővel kiderült, hogy a promise-ok is képesek bonyolult kódot szülni. Ezt a problémát analógia alapján promise hell-nek nevezték el.

Nézzük meg ezt a problémát kódpéldákon keresztül. Legyen egy getSmth függvényünk, amely kap egy paramétert és visszaad egy eredményt ennek a paraméternek a függvényében:

javascriptfunction getSmth(num) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * num), 1000)
  });
}

Ebben az esetben egy hasznos műveletet szimulálunk (például adatok lekérését a szerverről). A szimuláció érdekében egyszerűen egy számot adunk át paraméterként, és egy másodperc múlva visszaadjuk a szám négyzetét.

Most pedig használjuk a getSmth függvényünket egy másik függvényen belül:

javascriptfunction func() {
  getSmth(2).then(res => {
    console.log(res); // kiírja a 4-et
  });
}

func();

Első probléma

Az egymást követő then szerkezetek sokasága megnehezíti a kód megértését:

javascriptfunction func(){
  getSmth(2).then(res1 => {
    // csinálunk valamit
  }).then(res2 => {
    // csinálunk valamit
  }).then(res3 => {
    // csinálunk valamit
  }).then(res4 => {
    // csinálunk valamit
  }).then(res5 => {
    // csinálunk valamit
  }).then(res6 => {
    // csinálunk valamit
  });
}

func();

Második probléma

Van egy másik jellegű probléma is. Tegyük fel, hogy most kétszer szeretnénk használni a függvényünket, majd összegezni az eredményeket. Ennek eredményeképpen ilyen kódot kapunk:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(3).then(res2 => {
      console.log(res1 + res2); // kiírja a 13-at
    });
  });
}

func();

Már emlékeztet a callback hell-re, nem igaz? Adjunk hozzá még egy függvényhívást - a kód még rosszabb lesz:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(3).then(res2 => {
      getSmth(4).then(res3 => {
        console.log(res1 + res2 + res3);
      });
    });
  });
}

func();

Természetesen használhatnánk a Promise.all-t:

javascriptfunction func() {
  Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
    console.log(res[0] + res[1] + res[2]);
  });
}

func();

De vajon ugyanazt kaptuk-e? Nem! Az első esetben minden új függvény megvárja az előző promise befejeződését, míg a második esetben - minden promise egyszerre fut le. Ez a különbség akkor lesz jelentős, amikor az előző hívás eredményét szeretnénk átadni a következő függvénynek:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(res1).then(res2 => {
      getSmth(res2).then(res3 => {
        console.log(res3);
      });
    });
  });
}

func();