2011-08-31 4 views
1

Ok, il me manque probablement quelque chose d'évident, et bien que j'aie essayé de trouver un exemple similaire, je ne peux pas trouver exactement ce que je veux faire. J'ai besoin d'une série d'appels ajax pour exécuter dans un ordre particulier. J'utilise le code suivant pour finaliser une transaction:Problèmes de chaînage différés jQuery

showStandbyDialog(); 
    $.when(function(){console.log('Paying Charges due before transaction');}) 
     .always(this.applyCredit(parseFloat($(this.currentChargesTarget).html()))) // Pay charges due before transaction 
     .always(function(){console.log('Applying renewals');}) 
     .always(this.applyRenewals()) // Apply Renewals 
     .always(function(){console.log('Paying renewal charges');}) 
     .always(this.applyCredit(this.renewCart.length * this.renewCost)) // Pay renewal charges 
     .always(function(){console.log('Applying checkouts');}) 
     .always(this.applyCheckOut()) // Apply checkouts 
     .always(function(){console.log('Paying checkout charges');}) 
     .always(this.applyCredit(this.cart.length * this.checkOutCost)) // Pay checkout charges 
     .always(function(){console.log('Applying card replacement');}) 
     .always(this.applyCardReplacement()) // Apply card replacement 
     .always(function(){console.log('Paying leftover charges');}) 
     .always(this.applyCredit(this.cardCost)) // Pay leftover charges 
     .always(function(){console.log('Finalizing Transaction');}) 
     .always(function(){ updateCharges(); bfwd.Patron.Transaction.reset(); hideStandbyDialog(); }); // Reset Transaction and clear standby dialog 

Maintenant, je l'ai essayé, .done, .alors, et à peu près .anything() mais le code console.log() dans la fonction poignée de this.applyCredit() TOUJOURS se connecter après le fichier console.log ('Finalizing Transaction'). Chaque appel de this.function() renvoie une méthode jquery différée au cas où vous vous poseriez la question.

+2

Certaines de ces fonctions sont-elles asynchrones? Sinon, il n'y a aucune raison d'utiliser des reports. Créez simplement une fonction qui appelle toutes ces autres fonctions dans la séquence appropriée dans la programmation procédurale directe. Si elles sont asynchrones, indiquez-leur le code pour qu'elles puissent évaluer si vous utilisez les API différées de manière appropriée. – jfriend00

+0

Il a dit qu'il s'agissait d'une série d'appels ajax donc j'ai juste supposé ... –

+0

Désolé, je n'ai pas remarqué ces commentaires. Je suppose que c'est pas mal de poster le code. Une seconde. – LordZardeck

Répondre

8

Je refais complètement mon jsFiddle ici: http://jsfiddle.net/JohnMunsch/nxPn3/

environ 10 fois :)

.always() retournait le même objet différé (ou promesse) qui avait terminé dans la première .Lorsque() à toutes les autres fonctions .always(). Alors ils sont partis en feu rapide. Cela ressemblait grosso modo à ceci.

Step 1: log. 
Step 2: kick off ajax call, log, kick off ajax call, log, kick off ajax call, log, etc. etc. 

Je ne vois pas vraiment jusqu'à ce que je mets minuteries dans chacune de mes fonctions « appel ajax » pour les faire retarder un certain temps. Puis j'ai continué à avoir le problème de, comment puis-je faire cela sans imbriquer chaque étape suivante dans la fonction .done() de l'étape précédente?

Ma solution à celui-ci ne peut pas être la plus gracieuse, mais cela a fonctionné. J'ai créé un ensemble complet d'objets différés à l'avance et je les utilise pour empêcher le démarrage de chaque étape successive jusqu'à ce que l'étape précédente soit marquée résolue ou rejetée.

Voici un extrait de cette:

console.log('Paying Charges due before transaction'); 
var step1 = applyCredit("parseFloat($(this.currentChargesTarget).html())"); 
var step2 = new $.Deferred(); 
var step3 = new $.Deferred(); 

$.when(step1).done(function(){ 
    console.log('Applying renewals'); 
    $.when(applyRenewals()).done(function() { 
     step2.resolve(); 
    }); 
}).fail(function() { step2.reject() }); 

$.when(step2).done(function(){ 
    console.log('Paying renewal charges'); 
    $.when(applyCredit("some subcalc")).done(function() { 
     step3.resolve(); 
    }); 
}).fail(function() { step3.reject() }); 

Maintenant, lorsque vous exécutez la jsFiddle, chaque marches d'appel de fonction le long d'une ligne parfaite. La seconde ne commence pas tant que la première n'est pas terminée et la troisième ne peut pas commencer avant que la seconde ne soit terminée ...

+0

bien, j'ai vérifié et il retourne un objet avec toutes les fonctions .then et .done et tout. Pour être exact, il retourne ceci: jQuery.post() – LordZardeck

+1

MERCI BEAUCOUP. Cela a fonctionné PARFAITEMENT. Je vais certainement garder cela dans ma base de connaissances car il y a beaucoup de choses dans mon programme qui doivent fonctionner en synchronisation. – LordZardeck

4

OK, ayant compris ma première réponse à comment faire ce que vous avez demandé, voici ma deuxième répondre. Ne fais pas ça. Ne pas utiliser le client pour séquencer un processus financier en huit étapes sur le serveur. Heck, ne l'utilisez pas pour séquencer un processus financier en deux étapes sur le serveur. Que se passe-t-il lorsque le serveur tombe en panne, que l'utilisateur ferme son ordinateur portable ou perd sa connectivité Internet? Vous vous retrouvez avec peut-être les étapes 1 à 3 terminées ou 1 à 5 sorties d'une séquence qui devait être exécutée en tant qu'unité.

Marque ONE Appel AJAX sur le serveur et fournir les informations nécessaires pour effectuer les huit étapes. Sur le serveur, utilisez une transaction prise en charge par votre serveur si possible ou utilisez une transaction de base de données pour vous assurer que toutes les opérations aboutissent ou échouent ensemble et que tout soit restauré dans son état initial en cas de défaillance. Ensuite, vous pouvez rapporter sur les résultats de ce qui s'est passé, y compris les détails sur chaque étape si vous en avez besoin ou si vous voulez, de retour au client.

+1

La raison pour laquelle je dois faire un à la fois est que chaque action peut avoir un échec. Et chaque action est supposée vérifier un échec avant de permettre au suivant de continuer (pas encore implémenté comme vous pouvez le voir). Si l'un échoue, il arrête le processus, alerte l'utilisateur et laisse le reste des données intactes pour que l'utilisateur ne perde pas sa progression. – LordZardeck

+0

Je comprends aussi que je pourrais trouver un moyen de l'écrire pour que le serveur s'occupe de tout, et je vais probablement le réécrire pour que ça le fasse, mon projet n'est pas très inquiet pour le moment et je suis plus intéressé à faire en sorte que tout fonctionne en premier. Mais vous avez un point et avez raison. Le serveur doit gérer toutes les données et la logique, et le client affiche ces informations. Je voudrais pouvoir marquer les deux comme une réponse. – LordZardeck

Questions connexes