Il existe une tonne de bibliothèques qui aident à réparer les couches du syndrome de rappel.
En fait, il y en a trop, lequel utiliser?
J'utilise Async.js .
Async est un module utilitaire qui fournit des fonctions simples et puissantes pour travailler avec JavaScript asynchrone. Bien que conçu à l'origine pour être utilisé avec node.js, il peut également être utilisé directement dans le navigateur.
Exemples
async.map(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
async.filter(['file1','file2','file3'], path.exists, function(results){
// results now equals an array of the existing files
});
async.parallel([
function(){ ... },
function(){ ... }
], callback);
async.series([
function(){ ... },
function(){ ... }
]);
J'aime utiliser promesses de Q :
Si une fonction ne peut pas retourner une valeur ou lever une exception sans bloquer, elle peut renvoyer une promesse à la place. Une promesse est un objet qui représente la valeur de retour ou l'exception levée que la fonction peut éventuellement fournir. Une promesse peut également être utilisée comme proxy pour un objet distant pour surmonter la latence.
Au premier passage, les promesses peuvent atténuer la "Pyramide de Doom": la situation où le code marche vers la droite plus vite qu'il ne marche en avant.
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
Avec une bibliothèque de promesses, vous pouvez aplatir la pyramide.
Q.fcall(step1)
.then(step2)
.then(step3)
.then(step4)
.then(function (value4) {
// Do something with value4
}, function (error) {
// Handle any error from step1 through step4
})
.done();
Avec cette approche, vous obtenez également une propagation d'erreur implicite, tout comme try, catch et enfin. Une erreur à l'étape 1 ira jusqu'à l'étape 5, où elle est détectée et gérée.
L'approche de rappel est appelée "inversion de contrôle". Une fonction qui accepte un rappel au lieu d'une valeur de retour dit: "Ne m'appelle pas, je t'appellerai". Promet d'annuler l'inversion, séparant proprement les arguments d'entrée des arguments de flux de contrôle. Cela simplifie l'utilisation et la création d'API, en particulier les arguments variadic, repos et spread.
Le problème que j'ai avec les autres bibliothèques de synchronisation est qu'elles m'ont souvent demandé de définir toutes mes tâches au début, et n'ont pas proposé une API claire et intuitive que j'ai trouvée. Je voulais simplement pousser des tâches vers un groupe, n'importe quand et n'importe où, puis exécuter ce groupe en parallèle ou en série.
J'adore la fonctionnalité de flux à l'intérieur TaskGroup , et je l'ai utilisée pour de nombreux grands projets, y compris DocPad et BugHerd . Des exemples sont dans le fichier README.