Le problème de l'enfer des promesses en JavaScript
Vous savez déjà que les promesses ont été créées pour résoudre le problème de l'enfer des rappels (callback hell). Cependant, avec le temps, il s'est avéré que les promesses sont également capables de générer un code complexe. Ce problème, par analogie, a été nommé promise hell.
Examinons ce problème à l'aide d'exemples de
code. Supposons que nous ayons une fonction getSmth,
prenant un paramètre et renvoyant un résultat
en fonction de ce paramètre :
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
Dans ce cas, nous simulons une opération utile (par exemple, la récupération de données depuis un serveur). Pour la simulation, nous passons simplement un nombre en paramètre et renvoyons le carré de ce nombre après une seconde.
Utilisons maintenant notre fonction
getSmth à l'intérieur d'une autre fonction :
function func() {
getSmth(2).then(res => {
console.log(res); // affichera 4
});
}
func();
Premier problème
De multiples constructions then
qui se suivent rendent le code difficile à comprendre :
function func(){
getSmth(2).then(res1 => {
// faisons quelque chose
}).then(res2 => {
// faisons quelque chose
}).then(res3 => {
// faisons quelque chose
}).then(res4 => {
// faisons quelque chose
}).then(res5 => {
// faisons quelque chose
}).then(res6 => {
// faisons quelque chose
});
}
func();
Deuxième problème
Il existe un problème d'une autre nature. Supposons maintenant que nous souhaitions utiliser notre fonction deux fois, puis additionner les résultats. Nous obtiendrions un code comme celui-ci :
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // affichera 13
});
});
}
func();
Cela rappelle déjà l'enfer des rappels (callback hell), n'est-ce pas ? Ajoutons un autre appel de fonction - le code deviendra encore pire :
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
On pourrait, bien sûr, utiliser Promise.all :
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Mais, avons-nous obtenu la même chose ? Non ! Dans le premier cas, chaque nouvelle fonction attend la résolution de la promesse précédente, tandis que dans le second cas, toutes les promesses s'exécutent simultanément. Cette différence sera significative dans le cas où nous voudrions passer le résultat d'une fonction précédente à la fonction suivante :
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();