Quelle est la manière correcte de chaîner les appels asynchrones en javascript?

J'essaie de trouver la meilleure façon de créer des appels asynchrones lorsque chaque appel dépend de l'appel précédent à avoir terminé. En ce moment, je suis en chaînage des méthodes en appelant récursivement une fonction de processus définie comme illustré ci-dessous.

C'est ce que je fais actuellement.

var syncProduct = (function() { var done, log; var IN_CAT = 1, IN_TITLES = 2, IN_BINS = 3; var state = IN_CAT; var processNext = function(data) { switch(state) { case IN_CAT: SVC.sendJsonRequest(url("/api/lineplan/categories"), processNext); state = IN_TITLES; break; case IN_TITLES: log((data ? data.length : "No") + " categories retrieved!"); SVC.sendJsonRequest(url("/api/lineplan/titles"), processNext); state = IN_BINS; break; case IN_BINS: log((data ? data.length : "No") + " titles retrieved!"); SVC.sendJsonRequest(url("/api/lineplan/bins"), processNext); state = IN_MAJOR; break; default: log((data ? data.length : "No") + " bins retrieved!"); done(); break; } } return { start: function(doneCB, logCB) { done = doneCB; log = logCB; state = IN_CAT; processNext(); } } })(); 

J'appellerais ceci comme suit

 var log = function(message) { // Impl removed. } syncProduct.start(function() { log("Product Sync Complete!"); }, log); 

Bien que cela fonctionne parfaitement bien pour moi, je ne peux pas m'empêcher de penser qu'il doit y avoir une meilleure façon (plus simple). Que se passe-t-il plus tard lorsque mes appels récursifs deviennent trop profonds?

REMARQUE : je n'utilise pas javascript dans le navigateur mais nativement dans le cadre Titanium, cela ressemble à Javascript pour Node.js.

Il existe de nombreuses bibliothèques et outils qui assurent un encodage et un flux de contrôle asynchrone pour vous et ils viennent principalement dans deux saveurs principales:

  1. Bibliothèques de flux de contrôle

    Par exemple, voir async , seq et step (basé sur le rappel) ou Q et futures (promis basé). Le principal avantage est que ce ne sont que des bibliothèques JS plaines qui facilitent la douleur de la programmation asynchrone.

    Dans mon expérience personnelle, les bibliothèques basées sur les promesses ont tendance à conduire à un code qui ressemble plus au code synchrone habituel, puisque vous renvoyez des valeurs à l'aide du «retour» et que les valeurs prometteuses peuvent être transmises et stockées, de manière similaire aux valeurs réelles.

    D'autre part, le code basé sur la continuation est plus bas, car il manipule explicitement les chemins de code. Cela peut permettre un flux de contrôle plus flexible et une meilleure intégration avec les bibliothèques existantes, mais cela pourrait également conduire à un code plus rapide et moins intuitif.

  2. Compilateurs CPS Javascript

    L'extension de la langue pour ajouter un support natif aux coroutines / générateurs vous permet d'écrire un code asynchrone d'une manière très simple et joue bien avec le reste de la langue, ce qui signifie que vous pouvez utiliser Javascript si des instructions, des boucles, etc., au lieu d'avoir besoin de les répliquer avec des fonctions. Cela signifie également qu'il est très facile de convertir le code de synchronisation précédemment en une version asynchrone. Cependant, il y a l'inconvénient évident que tous les navigateurs ne fonctionneront pas dans votre extension Javascript, vous devrez ajouter une étape de compilation dans votre processus de compilation pour convertir votre code en JS régulier avec des rappels en continu-passe-style. Quoi qu'il en soit, une alternative prometteuse est les générateurs dans la spécification Ecmascript 6 – alors que seul Firefox les supporte nativement à partir de maintenant, il existe des projets tels que le régénérateur et Traceur pour les compiler dans les rappels. Il existe également d'autres projets qui créent leur propre syntaxe asynchrone (puisque les générateurs es6 ne sont pas arrivés à l'époque). Dans cette catégorie, vous trouverez des choses telles que tamejs et Iced Coffeescript . Enfin, si vous utilisez Node.js, vous pouvez également regarder les Fibres .


Ma recommandation:

Si vous voulez juste quelque chose de simple qui ne compliquera pas votre processus de construction, je vous recommanderais avec n'importe quelle bibliothèque de contrôle-flux qui correspond le mieux à votre style personnel et aux bibliothèques que vous utilisez déjà.

Cependant, si vous prévoyez écrire beaucoup de code asynchrone compliqué et profondément intégré, je vous recommande vivement de chercher au moins une alternative basée sur le compilateur.