2010-04-02 10 views
6

Ho ereditato il codice JavaScript in cui il callback di successo di un gestore Ajax avvia un'altra chiamata Ajax in cui la callback di successo può o non può iniziare un'altra chiamata Ajax. Questo porta a funzioni anonime profondamente annidate. Forse c'è un modello di programmazione intelligente che evita l'annidamento profondo ed è più ASCIUTTO. Inoltre, c'è il problema delle variabili interne myVar1 e myVar2 che sono usate in tutte le funzioni.Schema di programmazione per appiattire callback ajax profondamente annidati?

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

Leggermente relazionato. Giocare AJAX "ping-pong" con il server è un modo sicuro per creare tempi di attesa extra. Potresti considerare se è possibile eseguire il lavoro in una sola richiesta, anche se ciò significa trasmettere più dati. – aaaaaaaaaaaa

risposta

3

Grazie al suggerimento di concatenamento e this comment, sono giunto alla seguente soluzione. L'ho provato e funziona. Probabilmente ci sono alcuni problemi relativi all'ambito e potresti refactoring di una classe generale ChainAjax. Ma per il momento, va bene.

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

Aggiornamento: Ho trovatothis nice presentation che si occupa anche di modelli di programmazione utili e best practice.

Aggiornamento 2012: Nel frattempo ci sono diverse librerie per la simulazione di un flusso sincrono con le funzioni asincrone: q, stratified.js e streamline.js

9

Non c'è bisogno per tutti i callback per essere anonimo e definita in linea, è possibile dichiarare altrove e basta usare il nome della funzione quando si specifica il callback.

+0

+1 Picchiami. –

1

Suggerirei di creare un piccolo strumento chiamato "catena ajax". Dagli ciò che vuoi che succeda in quale ordine, e poi spara. Accorderà ajax con successo fino a quando non si esaurirà la logica. Ti aiuterà a smettere di ripeterti e semplicemente a rappresentare il modello logico di ciò che vuoi fatto contro la codifica dei grugniti.

0

Si potrebbe fare questo con Frame.js come questo:

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