2013-05-16 12 views
18

Jak mogę dokonać tego dziełanode.js asynchroniczny synchronizować

var asyncToSync = syncFunc(); 

function syncFunc() { 
    var sync = true; 
    var data = null; 
    query(params, function(result){ 
     data = result; 
     sync = false; 
    }); 
    while(sync) {} 
    return data; 
} 

Próbowałem dostać funkcję synchronizacji z asynchroniczny jedno, muszę go używać FreeTDS zapytanie asynchronicznej jako zsynchronizowane jeden

+4

asynchroniczne wywołania zwrotne zawsze uruchamiane po stos funkcja wyczyszczone. Dlatego nie jest możliwe synchroniczne zwracanie wyniku ansyc. Każda funkcja synchroniczna, która zainicjowała działanie asynchroniczne, musi koniecznie powrócić przed rozpoczęciem akcji asynchronicznej. ** Zamiast **, chcesz uczynić twoją zewnętrzną funkcję * także * asynchroniczną, przyjmując wywołanie zwrotne, które jest wywoływane wewnątrz wywołania zwrotnego do 'zapytania'. – apsillers

+1

Czy funkcja zapytania wykonuje wywołanie bazy danych? Jeśli tak, klient DB może zapewnić synchroniczną wersję tej funkcji zapytania. – helpermethod

+0

Powiel: [Jak blokować asynchroniczne funkcje w JavaScript] (http://stackoverflow.com/questions/4345945/how-to-block-on-asynchronous-functions-in-javascript) (ale nie wiele dobrych odpowiedzi wyjaśniających) – apsillers

Odpowiedz

12

Użyj deasync - modułu napisanego w C++, który udostępnia pętlę zdarzeń Node.js do JavaScript. Moduł eksponuje także funkcję sleep, która blokuje kolejny kod, ale nie blokuje całego wątku ani nie powoduje zajętości oczekiwania. Można umieścić funkcję sleep w pętli while:

var asyncToSync = syncFunc(); 

function syncFunc() { 
    var sync = true; 
    var data = null; 
    query(params, function(result){ 
     data = result; 
     sync = false; 
    }); 
    while(sync) {require('deasync').sleep(100);} 
    return data; 
} 
+1

Jest to jedyny, którego nie trzeba uruchamiać wewnątrz światłowodu (którego nie zawsze można wykonać, jeśli nie kontrolujesz kodu wywołującego). – tmandry

+0

NIESAMOWITE !!! Lubię deasync – Aminadav

+0

Rzeczywiście! To jest jedyny, który działał w moim przypadku. Dzięki! – yoshi

9

Można zrobić z node-sync lib

var sync = require('sync'); 

sync(function(){ 
    var result = query.sync(query, params); 
    // result can be used immediately 
}) 

Zawiadomienie: zapytanie musi używać standart rozmowy zwrotnej (z błędem): pierwszy wywołania zwrotnego (błąd, wynik). Jeśli nie możesz zmienić metody zapytania, po prostu utwórz wrapper .async() (patrz link github).

+1

Mam funkcję asynchronizacji z błędem wywołania zwrotnego i ponownymi uruchomieniami, czy "sync (function() {})" jest w stanie zwrócić wartość w normalnej funkcji synchronizacji js? – user840250

+0

Nr sync() to tylko nowy kontekst wątku. Nic nie retunuje. Po prostu zapakuj cały kod i możesz użyć .sync na funkcjach asynchronicznych. –

3

Używam z powodzeniem syncrhonize.js. Istnieje nawet oczekujące żądanie ściągnięcia (które działa całkiem dobrze) w celu obsługi funkcji asynchronicznych, które mają wiele parametrów. Znacznie lepsze i łatwiejsze w użyciu niż imho synchronizacji węzła. Dodana premia, którą ma łatwa do zrozumienia i dokładna dokumentacja, natomiast synchronizacja węzła nie.

1

Problem polega na tym, że twoja napięta pętla blokuje się. Więc nie sądzę, że Twój callback zapytania zostanie kiedykolwiek uruchomiony. Myślę, że musisz użyć funkcji setTimeout lub podobnej, aby uniemożliwić blokowanie funkcji, ale jeśli to zrobisz, funkcja zostanie zwrócona przed wywołaniem wywołania zwrotnego. Ta funkcjonalność musi być zaimplementowana na niższym poziomie.

Jeśli jesteś w przeglądarce, możesz wypisać this article. W węźle musisz polegać na implementacji tego, o co pytasz. Może, ale nie musi, zapewniać metody synchroniczne.

7

Obecnie ten generator wzór może być fantastycznym rozwiązaniem w wielu sytuacjach:

// nodejs script doing sequential prompts using async readline.question function 

var main = (function*() { 

    // just import and initialize 'readline' in nodejs 
    var r = require('readline') 
    var rl = r.createInterface({input: process.stdin, output: process.stdout }) 

    // magic here, the callback is the iterator.next 
    var answerA = yield rl.question('do you want this? ', res=>main.next(res))  

    // and again, in a sync fashion 
    var answerB = yield rl.question('are you sure? ', res=>main.next(res))   

    // readline boilerplate 
    rl.close() 

    console.log(answerA, answerB) 

})() // <-- executed: iterator created from generator 
main.next()  // kick off the iterator, 
       // runs until the first 'yield', including rightmost code 
       // and waits until another main.next() happens