2010-04-02 9 views
6

Ich habe JavaScript-Code geerbt, bei dem der Erfolgsrückruf eines Ajax-Handlers einen weiteren Ajax-Aufruf initiiert, bei dem der Erfolgsrückruf einen weiteren Ajax-Aufruf auslösen kann oder auch nicht. Dies führt zu tief verschachtelten anonymen Funktionen. Vielleicht gibt es ein cleveres Programmiermuster, das die Tiefenverschachtelung vermeidet und eher TROCKEN ist. Außerdem gibt es das Problem der inneren Variablen myVar1 und myVar2, die in allen Funktionen verwendet werden.Programmiermuster, um tief verschachtelte Ajax Callbacks zu glätten?

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

Leicht verbunden. Das Spielen von AJAX "Ping-Pong" mit dem Server ist eine sichere Möglichkeit, zusätzliche Wartezeiten zu schaffen. Sie sollten überlegen, ob es möglich ist, den Auftrag in nur einer Anforderung auszuführen, selbst wenn das bedeutet, dass mehr Daten übertragen werden müssen. – aaaaaaaaaaaa

Antwort

3

Dank der Verkettung Hinweis und this comment, bin ich zu der folgenden Lösung gekommen. Ich habe es getestet und es funktioniert. Es gibt wahrscheinlich einige Problembereiche und Sie könnten eine generelle ChainAjax-Klasse umgestalten. Aber vorerst ist das in Ordnung.

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(); 
    } 
}); 

Update: fand ich this nice presentation, die auch mit nützlichen Programmierung Muster und Best Practices beschäftigt.

-Update 2012: In der Zwischenzeit gibt es mehrere Bibliotheken für einen synchronen Fluß mit asynchronen Funktionen zu simulieren: q, stratified.js und streamline.js

9

Es gibt keine Notwendigkeit für alle Rückrufe Inline anonym und definiert zu sein, können Sie sie an andere Stelle erklären und nur die Funktionsnamen verwenden, wenn Sie den Rückruf angeben.

+0

+1 Beat mich dazu. –

1

Ich würde vorschlagen, ein kleines Werkzeug namens "Chain Ajax" zu erstellen. Sie geben ihm, was Sie in welcher Reihenfolge passieren wollen, und dann feuern Sie. Es wird Ajax auf Erfolg ketten, bis die ganze Logik abläuft. Es wird Ihnen helfen, sich nicht mehr zu wiederholen und nur das logische Modell dessen, was Sie tun wollen, gegen grunt-coding darzustellen.

0

Man könnte dies wie folgt mit Frame.js tun:

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(); 
    } 
}); 
Verwandte Themen