Quelle est la bonne façon d'enchaîner les appels asynchrones en javascript?

j'essaie de trouver la meilleure façon de créer des appels asynchrones lors de chaque appel dépend du précédent appel d'avoir terminé. En ce moment, j'enchaîne les 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();
        }
    }
})();

Je l'appellerais alors comme suit

var log = function(message) {
    // Impl removed.
}

syncProduct.start(function() {
    log("Product Sync Complete!");
}, log);

bien que cela fonctionne parfaitement pour moi Je ne peux pas m'empêcher de penser qu'il doit y avoir un mieux (plus simple). Que se passe-t-il plus tard quand mes appels récursifs deviennent trop profonds?

NOTE : Je n'utilise pas javascript dans le navigateur mais nativement dans le cadre du titane, c'est un peu comme Javascript pour Noeud.js.

16
demandé sur Brett Ryan 2012-02-24 18:43:18

1 réponses

il y a beaucoup de bibliothèques et d'outils qui font de l'enchaînement asynchrone et du contrôle-flux pour vous et ils viennent principalement en deux saveurs principales:

  1. bibliothèques de flux de commande

    voir, Par exemple, async , seq et étape (rappel) ou Q et futures (promesse). Le principal avantage de celles-ci est qu'elles ne sont que des bibliothèques JS plains qui soulagent la douleur de la programmation asynchrone.

    d'après mon expérience personnelle, les bibliothèques basées sur des promesses ont tendance à conduire à un code qui ressemble plus au code synchrone habituel, puisque vous retournez des valeurs en utilisant" return " et que les valeurs promises peuvent être passées et stockées autour, de la même manière que les valeurs réelles.

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

  2. compilateurs Javascript CPS

    étendre le langage pour ajouter un support natif pour coroutines / generators vous permet d'écrire du 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 les déclarations, boucles, etc au lieu d'avoir besoin de les répliquer avec des fonctions. Cela signifie aussi qu'il est très facile de convertir le code sync en une version asynchrone. Cependant, il y a l'inconvénient évident que tous les navigateurs n'exécuteront pas votre extension Javascript, donc vous devrez ajouter une étape de compilation dans votre processus de compilation pour convertir votre code en js régulier avec des callbacks dans le style continuation-passing. 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 y a des projets tels que regenerator et Traceur pour les compiler à des callbacks. Il y a aussi d'autres projets qui créent leur propre syntaxe asynchrone (puisque les générateurs es6 n'étaient pas revenus à l'époque). Dans cette catégorie, vous trouverez des choses comme tamejs et Ice Coffeescript . Enfin, si vous utilisez le Nœud.js de là, vous pouvez également jeter un oeil à Fibres .


ma recommandation:

si vous voulez juste quelque chose de simple qui ne compliquera pas votre processus de construction, je recommande d'aller 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 d'écrire beaucoup de code asynchrone compliqué et profondément intégré, je recommande fortement au moins d'étudier une alternative basée sur le compilateur.

26
répondu hugomg 2014-01-15 00:41:04