2010-05-12 17 views
5

Sequenziale Le chiamate asincrone sono lorde. C'è una soluzione più leggibile?Come evitare le funzioni annidate quando si utilizza AJAX?

Il problema è questo è difficile da seguire:

ajaxOne(function() { 
    // do something 
    ajaxTwo(function() { 
    // do something 
    ajaxThree() 
    }); 
}); 

in cui le funzioni anonime sono callback che vengono chiamati risposta del server.

Sto utilizzando un'API di terze parti per effettuare chiamate AJAX, quindi ho bisogno di una soluzione generica.

risposta

3

programmazione funzionale al soccorso! jsdeferred vi permette di scrivere il tuo esempio in questo modo:

next(ajaxOne).next(ajaxTwo).next(ajaxThree).error(function(e){alert('An error happened:' + e)}) 

ciascuno dei "sequenziale" ajaxOne/due/tre funzioni riceve il risultato restituito del suo predecessore come parametro. Se è necessario passare altri parametri, è possibile esporli in un oggetto globale prima di richiamare la catena ajax.

+0

Anche se questo approccio richiede molto più impegno, sicuramente è molto bello e pulito :) Ma non è davvero una questione di "programmazione funzionale". – selfawaresoup

+0

Sembra davvero interessante, ma non riesco a capire come la classe differita funzioni internamente. –

+0

Uno sguardo alla sorgente di jsdeferred (http://github.com/cho45/jsdeferred/blob/master/jsdeferred.js) ti dice che la prossima funzione aspetta semplicemente che arrivi la prima chiamata ajax (usando setTimeout) e poi manda il prossimo. – fbuchinger

1

Se si dispone di una sola funzione nidificata, è ok lasciare invariato, ma se si dispone di più chiamate nidificate, è consigliabile considerare queste callback in un metodo separato e chiamarlo dalla funzione nidificata ...

0

Se non è necessario l'ambito di chiusura nei callback, che probabilmente non lo faranno, è possibile semplicemente mettere i callback in funzioni separate e chiamarli con il loro nome. del tipo:

var ajaxOne = function() { 
    doTheAjax(callbackOne); 
} 
var callbackOne = function() { 
    //funny things ... 
    doTheAjax(callbackTwo); 
} 
var callbackTwo = function() { 
    //even more funny things ... 
} 
+0

La mia domanda era probabilmente mal formata. Questo è in realtà il metodo che utilizzo poiché la linea diventerebbe troppo grande nel mio esempio. Tuttavia, la logica è difficile da seguire perché le chiamate devono ancora essere tracciate. –

1

Prima devo ammettere, sono relativamente nuovo a JavaScript, ma recentemente ho riscontrato lo stesso problema durante l'utilizzo della funzione jQuery ajax. Ho dovuto caricare un paio di documenti tramite POST su un server in un certo ordine. Annidare tutte le richiamate avrebbe prodotto codice completamente incasinato. Ho pensato a una soluzione dopo aver letto le risposte e ho trovato una soluzione che funzionava bene. Esso utilizza una sola funzione con una clausola di interruttore per differenziare le diverse invocazioni di callback:

var callback = function(sCallIdentifier, callbackParameters){ 
    switch(sCallIdentifier){ 
    case "ajaxOne": 
     doYourStuff(callbackParameters); //do your stuff for ajaxOne 
     ajaxTwo(function(newCallbackParameters){ 
      /*define a anonymous function as actual method-callback and pass the call-identifier, together with all parameters, to your defined callback function*/ 
      callback("ajaxTwo", newCallbackParameters); 
     }); 
     break; 
    case "ajaxTwo": 
     doYourStuff(callbackParameters); 
     ajaxThree(function(newCallbackParameters){ 
      callback("ajaxThree", newCallbackParameters); 
     }); 
     break; 
    case "ajaxThree": 
     doYourStuff(); 
     break; 
} 
}); 

Se questa non è una buona idea, per favore fatemelo sapere. Come ho detto, non sono un esperto di JavaScript, ma ho funzionato abbastanza bene per me.

migliore, René

Edit:

Dopo un po 'ho scoperto che Promises sono un approccio molto migliore per risolvere questo problema.

Problemi correlati