2012-10-27 22 views
7

Mam następujący kod przykładowy - pierwsza część może wywołać połączenie asynchroniczne lub nie - tak czy inaczej powinna być kontynuowana. Nie mogę umieścić reszty kodu wewnątrz asynchronicznego wywołania zwrotnego, ponieważ musi działać, gdy warunek jest fałszywy. Jak to zrobić?Warunkowe wywoływanie funkcji asynchronicznej w węźle

if(condition) { 
    someAsyncRequest(function(error, result)) { 
     //do something then continue 
    } 
} 

//do this next whether condition is true or not 

Zakładam, że wprowadzenie kodu przyjść po w funkcji może być droga i wywołać tę funkcję wywołania asynchronicznego powyżej lub na wezwanie innego jeśli warunek jest fałszywy - ale czy istnieje alternatywny sposób to nie wymaga rozbijania go na funkcje?

+0

asynchroniczny-czeka pakiet może pomóc (pozwala pisać kod asynchroniczny w stylu synchronizacji, obsługuje wyjątki itp.) https://www.npmjs.com/package/asyncawait - taka składnia będzie również natywnie obsługiwana w przyszłych wersjach Węzłów, zobacz https: // github.com/nodejs/promises/issues/4 –

Odpowiedz

3

Wystarczy zadeklarować jakaś inna funkcja być uruchamiany, gdy jest to potrzebne:

var otherFunc = function() { 
    //do this next whether condition is true or not 
} 

if(condition) { 
    someAsyncRequest(function(error, result)) { 
     //do something then continue 

     otherFunc(); 
    } 
} else { 
    otherFunc(); 
} 
+3

Tak, właśnie to mam teraz, o czym już wspominałem - tylko zastanawiasz się, czy istnieje sposób, który uniknął enkapsulacji kodu w funkcji – cyberwombat

+0

@Yashua, nie, ponieważ ponieważ twój someSyncRequest jest asynchroniczny, nie możesz zagwarantować kiedy zostanie ono wykonane, a ponieważ JavaScript nie jest z natury * wielowątkowy *, nie można po prostu "wstrzymać" jakiejś części programu, dopóki nie zostanie wykonane pewne wywołanie asynchroniczne. W związku z tym należy zabezpieczyć część kodu, aby wykonać ją później w funkcji i wywołać ją w odpowiednim czasie (tj. Od razu lub tylko po wykonaniu kodu asynchronicznego). –

3

Po prostu kolejny sposób, aby to zrobić, to jak ja wydobywane wzór. Mogą istnieć pewne biblioteki (obietnice?), Które zajmują się tym samym.

function conditional(condition, conditional_fun, callback) { 
    if(condition) 
     return conditional_fun(callback); 
    return callback(); 
} 

a następnie w kodzie można napisać

conditional(something === undefined, 
      function(callback) { 
       fetch_that_something_async(function() { 
        callback(); 
       }); 
      }, 
      function() { 

         /// ... This is where your code would continue 


      }); 
0

polecam korzystania clojurescript który ma niesamowite core-async biblioteki, która sprawia, że ​​bardzo proste życie w kontaktach z połączeń asynchronicznych.

W twoim przypadku można napisać coś takiego:

(go 
    (when condition 
    (<! (someAsyncRequest))) 
    (otherCodeToHappenWhetherConditionIsTrueOrNot)) 

zanotować go makro, które powoduje, że organizm do uruchomienia asynchronicznie, a funkcja <! który będzie blokował aż funkcja asynchroniczny powróci. Ze względu na to, że funkcja <! znajduje się w stanie when, blokuje się tylko wtedy, gdy warunek jest spełniony.

+0

@kleopatra Proszę zobaczyć moje zmiany w odpowiedzi. Mam nadzieję, że teraz jest lepiej. – Asher

+0

dzięki za aktualizację :-) – kleopatra

7

Często używaną biblioteką w węźle jest Async (https://github.com/caolan/async). Ostatnio sprawdziłem, czy ma również obsługę przeglądarki, więc powinieneś móc npm/concat/minify tego w swojej dystrybucji. Jeśli używasz tego tylko po stronie serwera, powinieneś wziąć pod uwagę https://github.com/continuationlabs/insync, która jest nieco ulepszoną wersją Async, z usuniętą obsługą niektórych przeglądarek.

Jednym z typowych wzorców, których używam podczas używania warunkowych wywołań asynchronicznych, jest wypełnienie tablicy funkcjami, których chcę użyć w kolejności, i przekazanie ich do async.waterfall.

Podałem przykład poniżej.

var tasks = []; 

if (conditionOne) { 
    tasks.push(functionOne); 
} 

if (conditionTwo) { 
    tasks.push(functionTwo); 
} 

if (conditionThree) { 
    tasks.push(functionThree); 
} 

async.waterfall(tasks, function (err, result) { 
    // do something with the result. 
    // if any functions in the task throws an error, this function is 
    // immediately called with err == <that error> 
}); 

var functionOne = function(callback) { 
    // do something 
    // callback(null, some_result); 
}; 

var functionTwo = function(previousResult, callback) { 
    // do something with previous result if needed 
    // callback(null, previousResult, some_result); 
}; 

var functionThree = function(previousResult, callback) { 
    // do something with previous result if needed 
    // callback(null, some_result); 
}; 

Oczywiście można użyć obietnic. W obu przypadkach lubię unikać wywoływania zwrotnego zagnieżdżania za pomocą asynchronizacji lub obietnic.

Niektóre rzeczy można uniknąć nie używając zagnieżdżone wywołania zwrotne są zmienne kolizji, podnoszące bugs „marszowa” w prawo>>>>, trudne do odczytania kodu, itp

+1

FWIW, Async jest alternatywą dla pierwszego omówionego tutaj anty-wzoru: http://webapplog.com/seven-things-you-should-stop-doing-with-node-js / – zedd45

Powiązane problemy