2010-05-12 11 views
5

Sekwencyjne wywołania asynchroniczne są obramowane. Czy istnieje bardziej czytelne rozwiązanie?Jak uniknąć zagnieżdżonych funkcji podczas korzystania z AJAX?

Problemem jest to trudne do naśladowania:

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

gdzie anonimowe funkcje wywołania zwrotne, które są wywoływane na odpowiedź serwera.

Używam API innej firmy do wykonywania wywołań AJAX, więc potrzebuję ogólnego rozwiązania.

Odpowiedz

3

programowanie funkcjonalne na ratunek! jsdeferred pozwala napisać przykład tak:

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

każdym „sekwencyjny” ajaxOne/dwa/trzy funkcje otrzymuje zwrócony wynik swojego poprzednika jako parametr. Jeśli potrzebujesz przekazać dodatkowe parametry, możesz odsłonić je w obiekcie globalnym przed wywołaniem łańcucha ajaxowego.

+0

Chociaż takie podejście wymaga znacznie więcej wysiłku, to z pewnością jest bardzo ładne i czyste :) Ale tak naprawdę nie jest to kwestia "programowania funkcjonalnego". – selfawaresoup

+0

To wygląda naprawdę fajnie, ale nie mogę zrozumieć, jak odroczona klasa działa wewnętrznie. –

+0

Spojrzenie na źródło jsdeferred (http://github.com/cho45/jsdeferred/blob/master/jsdeferred.js) mówi, że następna funkcja po prostu czeka na pierwsze wywołanie ajax (przy użyciu setTimeout), a następnie wysyła Następny. – fbuchinger

1

Jeśli masz tylko jedną zagnieżdżoną funkcję, możesz pozostawić ją tak jak jest, ale jeśli masz kilka zagnieżdżonych połączeń, powinieneś rozważyć zapisanie tych wywołań zwrotnych w osobnej metodzie i wywołanie go z zagnieżdżonej funkcji ...

ajaxOne(function(result) { handleAjaxOneCallback(result, someExtraNeededArg); }); 

function handleAjaxOneCallback(result, someExtraNeededParam) { 
    // do something 

    ajaxTwo(function(result) { handleAjaxTwoCallback(result, myFoo, myBar); }); 
} 

function handleAjaxTwoCallback(result, foo, bar) { 
    // do something 

    ajaxThree(/* ... */); 
} 
0

Jeśli nie potrzebujesz zakresu zamknięcia w swoich wywołaniach zwrotnych, co prawdopodobnie nie będzie możliwe, możesz po prostu odłożyć wywołania zwrotne na oddzielne funkcje i wywołać je po imieniu. na przykład:

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

Moje pytanie było prawdopodobnie źle sformułowane. Jest to właściwie metoda, której używam, ponieważ linia w moim przykładzie byłaby zbyt duża. Jednak logika jest trudna do naśladowania, ponieważ połączenia wciąż muszą być śledzone. –

1

Najpierw muszę przyznać, jestem stosunkowo nowy w JavaScript, ale ostatnio napotkałem ten sam problem podczas korzystania z funkcji ajax jQuery. Musiałem przesłać kilka dokumentów przez POST do serwera w określonej kolejności. Zagnieżdżanie wszystkich połączeń zwrotnych spowodowałoby wygenerowanie całkowicie pomieszanego kodu. Myślałem o rozwiązaniu po przeczytaniu odpowiedzi i wymyśliłem rozwiązanie, które dobrze mi pasowało. Wykorzystuje tylko jedną funkcję z klauzulą ​​przełącznika w celu odróżnienia różnych wywołań zwrotnych:

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

Jeśli to nie jest dobry pomysł, proszę dać mi znać. Jak już powiedziałem, nie jestem ekspertem od JavaScript, ale mi się udało.

Best, René

Edit:

Po pewnym czasie okazało się, że Promises są o wiele lepsze podejście do rozwiązania tego problemu.

Powiązane problemy