16

Próbuję znaleźć najlepszy sposób tworzenia połączeń asynchronicznych, gdy każde połączenie zależy od wcześniejszego połączenia. W tej chwili używam metod, wywołując rekurencyjnie zdefiniowaną funkcję procesu, jak pokazano poniżej.Jaki jest poprawny sposób połączenia połączeń asynchronicznych w javascript?

Właśnie to robię.

var syncProduct = (function() { 
    var done, log; 
    var IN_CAT = 1, IN_TITLES = 2, IN_BINS = 3; 
    var state = IN_CAT; 
    var processNext = function(data) { 
     switch(state) { 
      case IN_CAT: 
       SVC.sendJsonRequest(url("/api/lineplan/categories"), processNext); 
       state = IN_TITLES; 
       break; 
      case IN_TITLES: 
       log((data ? data.length : "No") + " categories retrieved!"); 
       SVC.sendJsonRequest(url("/api/lineplan/titles"), processNext); 
       state = IN_BINS; 
       break; 
      case IN_BINS: 
       log((data ? data.length : "No") + " titles retrieved!"); 
       SVC.sendJsonRequest(url("/api/lineplan/bins"), processNext); 
       state = IN_MAJOR; 
       break; 
      default: 
       log((data ? data.length : "No") + " bins retrieved!"); 
       done(); 
       break; 
     } 
    } 
    return { 
     start: function(doneCB, logCB) { 
      done = doneCB; log = logCB; state = IN_CAT; 
      processNext(); 
     } 
    } 
})(); 

bym wtedy nazywamy to następująco

var log = function(message) { 
    // Impl removed. 
} 

syncProduct.start(function() { 
    log("Product Sync Complete!"); 
}, log); 

Chociaż to działa perfekcyjnie dla mnie nie mogę pomóc, ale myślę, że musi być lepszy (prostszy) sposób. Co stanie się później, gdy moje rekurencyjne połączenia będą zbyt głębokie?

UWAGA: Nie używam javascript w przeglądarce, ale natywnie w ramach Titanium, jest to podobne do Javascriptu dla Node.js.

+1

Czy spojrzał na „obietnic”? Mogą pasować fajnie. [To jest biblioteka implementująca go dla Węzła] (https://github.com/kriskowal/q). – pimvdb

+0

Ta biblioteka wygląda genialnie pimvdb, myślę, że będę używał tego. –

Odpowiedz

26

Istnieje wiele bibliotek i narzędzi, które wykonują asynchronicznej łańcuchowym i kontroli przepływu do was i oni głównie występują w dwóch podstawowych smaków:

  1. biblioteki sterowania przepływem

    Na przykład, patrz async, seq i step (w oparciu o wywołania zwrotne) lub Q i futures (oparte na obietnicy). Główną ich zaletą jest to, że są po prostu bibliotekami JS, które ułatwiają programowanie asynchroniczne.

    Z mojego osobistego doświadczenia wynika, że ​​biblioteki oparte na obietnicach zwykle prowadzą do kodu, który wygląda bardziej jak zwykły kod synchroniczny, ponieważ zwracasz wartości za pomocą "return", a ponieważ obietnice mogą być przekazywane i przechowywane, podobnie jak w rzeczywistych wartościach.

    Z drugiej strony kod oparty na kontynuacji jest bardziej niski, ponieważ w sposób wyraźny manipuluje ścieżkami kodu. Może to pozwolić na bardziej elastyczny przepływ sterowania i lepszą integrację z istniejącymi bibliotekami, ale może również prowadzić do większej ilości kodu kotłów i mniej intuicyjnego kodu.

  2. JavaScript CPS kompilatory

    Rozszerzenie języka dodać natywne wsparcie dla współprogram/Generatory umożliwia pisanie kodu asynchronicznego w bardzo prosty sposób i odgrywa ładne z resztą języku oznacza, że ​​można użyć JavaScript, jeśli instrukcje, pętle itp. zamiast potrzeby replikowania ich za pomocą funkcji. Oznacza to również, że bardzo łatwo jest przekonwertować poprzednio zsynchronizowany kod na wersję asynchroniczną. Jednak oczywistą wadą jest to, że nie każda przeglądarka będzie obsługiwać rozszerzenie Javascript, więc będziesz musiał dodać krok kompilacji do procesu budowania, aby przekonwertować swój kod do zwykłego JS z wywołania zwrotnego w stylu kontynuacji-przekazywania. Tak czy inaczej, jedną obiecującą alternatywą są generatory w specyfikacji Ecmascript 6 - chociaż tylko firefox wspiera je natywnie od teraz, istnieją takie projekty, jak regenerator i Traceur, aby skompilować je z powrotem do wywołań zwrotnych. Istnieją również inne projekty, które tworzą własną składnię asynchroniczną (ponieważ generatory es6 nie pojawiły się wtedy). W tej kategorii znajdziesz rzeczy takie jak tamejs i Iced Coffeescript. Na koniec, jeśli korzystasz z Node.js tam, możesz również rzucić okiem na Fibers.


Moja poleca:

Jeśli chcesz tylko coś prostego, że nie będzie komplikować gromadzeniu proccess, Polecam dzieje z tym, co kontrola przepływu biblioteka najlepiej pasuje do Twojego osobistego stylu i biblioteki, z których już korzystasz.

Jednakże, jeśli można oczekiwać, aby napisać wiele skomplikowanych i głęboko zintegrowanej kodu asynchronicznego, gorąco polecam przynajmniej patrząc na alternatywę kompilatora oparte.

+0

Doskonałe missingno, biblioteka 'Q', którą pimvdb wspomniał również w komentarzu do mojego pytania, wygląda idealnie. Czy mógłbyś wyrazić opinię na temat bibliotek, zanim zdecyduję się pójść ścieżką? Chyba nie chcę, ale jest to całkowicie blokujące połączenie przy pierwszym wywołaniu. –

+2

@BrettRyan: Właściwie to głównie praca z Dojo Toolkit rzeczy więc mam większość mojego doświadczenia ze swojej biblioteki obietnicy i nie dużego doświadczenia z alternatyw. Wszystkie style powinny być w stanie wykonać wszystkie niezbyt blokujące rzeczy, więc i tak powinieneś wyglądać bardziej na styl programowania. Jeśli musiałbym zacząć coś teraz chciałbym mocno rozważyć użycie kompilatora CPS - ja naprawdę nie wiem jak to będzie w rzeczywistości okazują się jednak teraz jestem trochę zmęczony konieczności ręcznego pisania kodu CPS i nadzieję na coś lepszy. – hugomg

+0

Dzięki missingno, używam Appcelerator Titanium Telefony SDK tak naprawdę nie chcą stawiać kolejne narzędzie do łańcucha narzędzi. Eksperymentowanie z biblioteką Q naprawdę wydaje się naturalne. –