Das Problem des Promise Hell in JavaScript

Sie wissen bereits, dass Promises erstellt wurden, um das Problem des Callback Hell zu lösen. Allerdings hat sich mit der Zeit herausgestellt, dass Promises auch komplexen Code erzeugen können. Dieses Problem wurde analog als promise hell bezeichnet.

Lassen Sie uns dieses Problem anhand von Codebeispielen betrachten. Angenommen, wir haben eine Funktion getSmth, die einen Parameter erhält und ein Ergebnis in Abhängigkeit von diesem Parameter zurückgibt:

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

In diesem Fall imitieren wir eine nützliche Operation (z. B. das Abrufen von Daten von einem Server). Zur Simulation übergeben wir einfach eine Zahl als Parameter und geben nach einer Sekunde das Quadrat dieser Zahl zurück.

Lassen Sie uns nun unsere Funktion getSmth innerhalb einer anderen Funktion verwenden:

javascriptfunction func() {
  getSmth(2).then(res => {
    console.log(res); // gibt 4 aus
  });
}

func();

Erstes Problem

Mehrere aufeinanderfolgende then Konstrukte erschweren das Verständnis des Codes:

javascriptfunction func(){
  getSmth(2).then(res1 => {
    // tun wir etwas
  }).then(res2 => {
    // tun wir etwas
  }).then(res3 => {
    // tun wir etwas
  }).then(res4 => {
    // tun wir etwas
  }).then(res5 => {
    // tun wir etwas
  }).then(res6 => {
    // tun wir etwas
  });
}

func();

Zweites Problem

Es gibt auch ein Problem anderer Art. Nehmen wir nun an, wir möchten unsere Funktion zweimal verwenden und dann die Ergebnisse summieren. Daraus ergibt sich folgender Code:

javascriptfunction func() {
  getSmth(2).then(res1 => {
    getSmth(3).then(res2 => {
      console.log(res1 + res2); // gibt 13 aus
    });
  });
}

func();

Erinnert schon an Callback Hell, nicht wahr? Fügen wir noch einen Funktionsaufruf hinzu - der Code wird noch schlimmer:

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

func();

Man könnte natürlich Promise.all verwenden:

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

func();

Aber haben wir damit dasselbe erreicht? Nein! Im ersten Fall wartet jede neue Funktion auf das Abschließen des vorherigen Promises, während im zweiten Fall alle Promises gleichzeitig ausgeführt werden. Dieser Unterschied ist wesentlich, wenn wir in die nächste Funktion den Aufruf der vorherigen übergeben wollen:

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

func();