2010-04-02 5 views
6

J'ai hérité du code JavaScript où le rappel de succès d'un gestionnaire Ajax initie un autre appel Ajax où le rappel de succès peut initier ou non un autre appel Ajax. Cela conduit à des fonctions anonymes profondément imbriquées. Peut-être qu'il y a un modèle de programmation intelligent qui évite l'emboîtement profond et qui est plus SEC. En outre, il y a le problème des variables internes myVar1 et myVar2 qui sont utilisées dans toutes les fonctions.Modèle de programmation pour aplanir les rappels ajax profondément imbriqués?

jQuery.extend(Application.Model.prototype, { 
    process: function() { 
     var myVar1; 
     // processing using myVar1; 
     jQuery.ajax({ 
      url:myurl1, 
      dataType:'json', 
      success:function(data) { 
       var myVar2; 
       // process data using myVar1, set state of myVar2, 
       // then send it back 
       jQuery.ajax({ 
        url:myurl2, 
        dataType:'json', 
        success:function(data) { 
         // do stuff with myVar1 and myVar2 
         if(!data.ok) { 
          jQuery.ajax({ 
           url:myurl2, 
           dataType:'json', 
           success:mycallback 
          }); 
         } 
         else { 
          mycallback(data); 
          } 

        } 
       }); 
      } 
     }); 
    } 
}); 
+1

Légèrement en relation. Jouer AJAX "ping-pong" avec le serveur est un moyen sûr de créer un temps d'attente supplémentaire. Vous voudrez peut-être considérer s'il est possible de faire le travail en une seule requête, même si cela implique de transmettre plus de données. – aaaaaaaaaaaa

Répondre

3

Merci à l'indice de chaînage et this comment, je suis venu à la solution suivante. Je l'ai testé et cela fonctionne. Il y a probablement des problèmes de portée et vous pourriez refactoriser une classe générale ChainAjax. Mais pour le moment, c'est ok.

jQuery.extend(MyApplication.Model.prototype, { 
    process: function() { 

     // private class for executing the Ajax calls 
     var myAjaxCalls = function(options) { 
      this.options = options; 
      this.myVar1 = null; 
      this.myVar2 =null;     
     } 
     jQuery.extend(myAjaxCalls.prototype, { 
      process1:function(data) { 
      // processsing using this.myVar1 
      this.myVar1 = 5; 
      return true; 
      }, 
      process2:function(data) { 
      this.myVar2 = 6;  
      if(data.ok) { 
       mycallback(data); 
      } 
      else { 
       return true; 
      } 
      }, 
      process3:function(data) { 
      // Process this.myVar1 and this.myVar 
      mycallback(data); 
      return false; 
      }, 
      chainAjax:function() { 
      if(this.options.length > 0) { 
       var opt = this.options.shift(); 
       var that = this; 
       jQuery.ajax({ 
       url:opt.url, 
       success:function(data) { 
        if(that[opt.callback](data)) { 
          that.chainAjax(); 
        } 
       } 
       }); 
      } 
      } 
     }); 
     // End private class 

     var calls = new myAjaxCalls([ 
      {url:'http://localhost/', callback:'process1'}, 
      {url:'http://localhost/', callback:'process2'}, 
      {url:'http://localhost/', callback:'process3'} 
     ]); 
     calls.chainAjax(); 
    } 
}); 

Mise à jour: Je trouve this nice presentation qui traite également des modèles de programmation utiles et les meilleures pratiques.

Mise à jour 2012: En attendant, il existe plusieurs bibliothèques pour simuler un flux synchrone avec des fonctions asynchrones: q, stratified.js et streamline.js

9

Il n'y a pas besoin de tous les callbacks d'être anonyme et définie en ligne, vous pouvez les déclarer ailleurs et il suffit d'utiliser le nom de la fonction lorsque vous spécifiez le rappel.

+0

+1 Battez-moi. –

1

Je suggère de créer un petit outil appelé "chaîne ajax". Vous lui donnez ce que vous voulez arriver dans quel ordre, puis le feu. Il enchaînera ajax sur le succès jusqu'à ce que toute la logique s'épuise. Cela vous aidera à cesser de vous répéter et à représenter simplement le modèle logique de ce que vous voulez faire par rapport au codage par grugeage.

0

Vous pouvez le faire avec Frame.js comme ceci:

jQuery.extend(Application.Model.prototype, { 
    process: function() { 
     var myVar1; 
     // processing using myVar1; 
     Frame(function(done){ 
      jQuery.ajax({ 
       url:myurl1, 
       dataType:'json', 
       success: done 
      }); 
     }); 
     Frame(function(done, data) { 
      var myVar2; 
      // process data using myVar1, set state of myVar2, 
      // then send it back 
      jQuery.ajax({ 
       url:myurl2, 
       dataType:'json', 
       success: done 
      }); 
     }); 
     Frame(function(done, data) { 
      // do stuff with myVar1 and myVar2 
      if(!data.ok) { 
       jQuery.ajax({ 
        url:myurl2, 
        dataType:'json', 
        success:done 
       }); 
      } 
      else { 
       done(data); 
      } 
     }); 
     Frame(function(done, data){ 
      mycallback(data); 
     }); 
     Frame.start(); 
    } 
}); 
Questions connexes