Callback Hell

Supposons deux fonctions asynchrones :

getCurrentCity(callback: (error, city: string) => void);

et

getWeatherInfo(city: string, callback: (error, weatherInfo: WeatherInfo) => void);

Avec des "callbacks" classiques, nous sommes amenés à utiliser ces fonctions de la façon suivante :

const handleError = error => {
console.error(`Something went wrong but I don't know how to handle it`);
};
​
getCurrentCity((error, city) => {
​
if (error != null) {
handleError(error);
return;
}
getWeatherInfo(city, (err, weatherInfo) => {
if (error != null) {
handleError(error);
}
console.log(`${city}: ${weatherInfo.temperature}`);
});
});

Ce cas est relativement simple mais manque déjà en lisibilité et présente déjà quelques erreurs.

Closure Cupide

A la ligne 12, le paramètre d'erreur a été nommé err mais à la ligne 14, c'est le paramètre error du closure parent qui est utilisé.

Plus les "callbacks" se cascadent plus ce type d'erreur a de chance de se produire.

Multi-purpose Error-First Callback

Le problème avec l'approche Error-First Callback utilisée dans notre exemple en suivant les conventions NodeJS, est que la même "callback" sert à deux finalités : le succès et l'échec ; avec cette approche, il arrive souvent d'omettre la gestion d'erreur et donc d'appeler l'étape suivante malgré tout.

C'est le cas de notre exemple où il nous manque un return après la ligne 15.

Pas de catch

Il est nécessaire d'appeler de capturer et gérer les erreurs de chaque appel.

Annulation

Il est impossible dans l'état d'annuler l'enchainement des traitements une fois lancé.

JavaScript Async Libraries

Bien sûr, il existe des librairies "cache-misère" telles que http://caolan.github.io/async/ mais elles sont progressivement abandonnées pour passer aux approches abordées dans les chapitres suivants.