Załóżmy, że utrzymujesz bibliotekę, która ujawnia funkcję getData
. Użytkownicy nazwać uzyskać rzeczywiste dane:
var output = getData();
Pod kaptur dane są zapisywane w pliku, dzięki czemu realizowane getData
przy użyciu node.js wbudowanej fs.readFileSync
. To oczywiste, że zarówno getData
i fs.readFileSync
są funkcjami synchronizacji. Pewnego dnia powiedziano Ci, aby przełączyć bazowe źródło danych do repozytorium, takiego jak MongoDB, do którego można uzyskać dostęp tylko asynchronicznie. Powiedziano ci również, abyś nie wkurzał swoich użytkowników, getData
API nie może zostać zmienione tak, aby zwracało jedynie obietnicę lub wymagało parametru wywołania zwrotnego. Jak spełniasz oba wymagania?
Funkcja asynchroniczna wykorzystująca wywołanie zwrotne / obietnicę to DNA języków JavasSript i Node.js. Każda nietrywialna aplikacja JS jest prawdopodobnie przesiąknięta tym stylem kodowania. Ale ta praktyka może łatwo doprowadzić do tak zwanej piramidy zagłady. Co gorsza, jeśli jakikolwiek kod w jakimkolwiek obiekcie wywołującym w łańcuchu wywołań zależy od wyniku funkcji asynchronicznej, ten kod również musi zostać opakowany w funkcję wywołania zwrotnego, nakładając na wywołującego ograniczenie stylu kodowania. Od czasu do czasu potrzebuję hermetyzowania funkcji asynchronicznej (często dostarczanej w bibliotece innej firmy) w funkcję synchronizacji, aby uniknąć masowego globalnego ponownego fakturowania. Poszukiwanie rozwiązania na ten temat zwykle kończyło się na Node Fiberslub pakiety npm pochodzące z niego. Ale włókna po prostu nie mogą rozwiązać problemu, z którym mam do czynienia. Nawet przykład podany przez autora Fibersa ilustruje brak:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
Rzeczywista wydajność:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Jeśli funkcja Fiber naprawdę zmienia uśpienie funkcji asynchronicznej w synchronizację, wynik powinien wyglądać następująco:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main
Stworzyłem kolejny prosty przykład w JSFiddle i szukam kodu, który zapewni oczekiwane wyniki. Przyjmuję rozwiązanie, które działa tylko w Node.js, więc możesz wymagać dowolnego pakietu npm, mimo że nie działa w JSFiddle.
Odpowiedzi:
deasync zamienia funkcję asynchroniczną w synchronizację, zaimplementowaną z mechanizmem blokującym, wywołując pętlę zdarzeń Node.js w warstwie JavaScript. W rezultacie deasync blokuje tylko kolejny kod przed uruchomieniem, bez blokowania całego wątku ani konieczności oczekiwania na zajętość. W tym module jest odpowiedź na wyzwanie jsFiddle:
(zastrzeżenie: jestem współautorem
deasync
. Moduł został utworzony po wysłaniu tego pytania i nie znalazł żadnej działającej propozycji.)źródło
function AnticipatedSyncFunction(){ var ret; setTimeout(function(){ var startdate = new Date() //console.log(startdate) ret = "hello" + startdate; },3000); while(ret === undefined) { require('deasync').runLoopOnce(); } return ret; } var output = AnticipatedSyncFunction(); var startdate = new Date() console.log(startdate) console.log("output="+output);
i spodziewam się, że dane wyjściowe będą miały 3 sekundy różnej daty!Istnieje również moduł synchronizacji npm. który służy do synchronizacji procesu wykonywania zapytania.
Jeśli chcesz uruchamiać zapytania równoległe w sposób synchroniczny, ogranicz węzeł, aby to zrobić, ponieważ nigdy nie czeka na odpowiedź. i moduł synchronizacji jest doskonały do tego rodzaju rozwiązań.
Przykładowy kod
odnośnik referencyjny: https://www.npmjs.com/package/sync
źródło
Tak. Wewnątrz włókna funkcja czeka przed zalogowaniem
ok
. Włókna nie sprawiają, że funkcje asynchroniczne są synchroniczne, ale pozwalają na pisanie kodu wyglądającego synchronicznie, który używa funkcji asynchronicznych, a następnie będzie działać asynchronicznie wewnątrz plikuFiber
.Nie możesz. Niemożliwe jest synchronizowanie kodu asynchronicznego. Będziesz musiał przewidzieć to w swoim kodzie globalnym i od początku napisać go w stylu asynchronicznym. To, czy zawiniesz globalny kod we włókno, użyjesz obietnic, generatorów obietnic czy prostych wywołań zwrotnych, zależy od twoich preferencji.
Mogą to zrobić zarówno obietnice, jak i włókna.
źródło
fs
metod synchronicznych .Musisz korzystać z obietnic:
Bardziej lubię definicje funkcji strzałek. Ale dowolny ciąg w postaci „() => {...}” można również zapisać jako „funkcja () {...}”
Zatem topDog nie jest asynchroniczny pomimo wywołania funkcji asynchronicznej.
EDYCJA: Zdaję sobie sprawę, że wiele razy trzeba zawinąć funkcję asynchroniczną wewnątrz funkcji synchronizacji, gdy znajduje się wewnątrz kontrolera. Oto sztuczka imprezowa w takich sytuacjach:
Wykorzystując to z wywołaniami zwrotnymi, możesz wykonać zawijanie, które nie używa obietnic:
Stosując tę sztuczkę do EventEmittera, możesz uzyskać te same wyniki. Zdefiniuj odbiornik EventEmittera, w którym zdefiniowałem wywołanie zwrotne, i wyemituj zdarzenie, w którym wywołałem wywołanie zwrotne.
źródło
Nie mogę znaleźć scenariusza, którego nie można rozwiązać za pomocą włókien węzłowych. Podany przykład przy użyciu węzłów-włókien zachowuje się zgodnie z oczekiwaniami. Kluczem jest uruchomienie całego odpowiedniego kodu wewnątrz światłowodu, więc nie trzeba rozpoczynać nowego włókna w przypadkowych pozycjach.
Zobaczmy przykład: Załóżmy, że używasz jakiegoś frameworka, który jest punktem wejścia do twojej aplikacji (nie możesz modyfikować tego frameworka). Ten framework ładuje moduły nodejs jako wtyczki i wywołuje niektóre metody we wtyczkach. Powiedzmy, że ten framework akceptuje tylko funkcje synchroniczne i sam nie używa włókien.
Istnieje biblioteka, której chcesz użyć w jednej ze swoich wtyczek, ale ta biblioteka jest asynchroniczna i nie chcesz jej też modyfikować.
Nie można uzyskać głównego wątku, gdy żadne włókno nie jest uruchomione, ale nadal można tworzyć wtyczki za pomocą włókien! Po prostu utwórz wpis opakowujący, który uruchamia cały framework wewnątrz włókna, abyś mógł wykonać wykonanie z wtyczek.
Wada: Jeśli platforma używa
setTimeout
lubPromise
s wewnętrznie, to wymknie się z kontekstu włókna. Można to obejść przez szyderczysetTimeout
,Promise.then
i wszyscy obsługi zdarzeń.Więc w ten sposób możesz wydobyć włókno do czasu
Promise
zostanie rozwiązane. Ten kod przyjmuje funkcję asynchroniczną (zwracająca obietnicę) i wznawia działanie włókna po rozwiązaniu obietnicy:framework-entry.js
async-lib.js
my-plugin.js
my-entry.js
Po uruchomieniu
node framework-entry.js
go wygeneruje błąd:Error: yield() called with no fiber running
. Jeśli uruchomisznode my-entry.js
, działa zgodnie z oczekiwaniami.źródło
Synchronizacja kodu Node.js jest niezbędna w kilku aspektach, takich jak baza danych. Jednak faktyczna zaleta Node.js polega na kodzie asynchronicznym. Ponieważ jest to jeden wątek nieblokujący.
możemy go zsynchronizować używając ważnej funkcjonalności Fibre () Używając await () i defer () wywołujemy wszystkie metody używając await (). następnie zamień funkcje zwrotne na defer ().
Normalny kod asynchroniczny, który wykorzystuje funkcje CallBack.
Zsynchronizuj powyższy kod za pomocą Fiber (), await () i defer ()
Mam nadzieję, że to pomoże. Dziękuję Ci
źródło
Obecnie ten wzorzec generatora może być rozwiązaniem w wielu sytuacjach.
Oto przykład sekwencyjnych monitów konsoli w nodejs używających funkcji async readline.question:
źródło
Nie powinieneś patrzeć na to, co dzieje się wokół połączenia, które tworzy włókno, ale raczej na to, co dzieje się wewnątrz włókna. Gdy jesteś w środku włókna, możesz programować w stylu synchronizacji. Na przykład:
Wewnątrz włókna, do którego dzwonisz
f1
,f2
isleep
jakby były zsynchronizowane.W typowej aplikacji internetowej światłowód zostanie utworzony w programie wysyłającym żądania HTTP. Gdy już to zrobisz, możesz napisać całą logikę obsługi żądań w stylu synchronizacji, nawet jeśli wywołuje ona funkcje asynchroniczne (FS, bazy danych itp.).
źródło
while(true) handleNextRequest()
pętla. Owinięcie każdej obsługi żądań w światłowodzie byłoby.Na początku zmagałem się z tym, korzystając z node.js, a async.js to najlepsza biblioteka, jaką znalazłem, aby pomóc ci sobie z tym poradzić. Jeśli chcesz pisać kod synchroniczny z węzłem, podejście jest takie.
ten program ZAWSZE wyprodukuje następujące ...
źródło
async
działa w twoim przykładzie b / c tomain
, co nie dba o rozmówcę. Wyobraź sobie, że cały kod jest opakowany w funkcję, która ma zwracać wynik jednego z wywołań funkcji asynchronicznej. Można łatwo sprawdzić, czy nie działa, dodającconsole.log('return');
na końcu kodu. W takim przypadku wyjściereturn
nastąpi po,in main
ale przedstep 1
.Javascript jest językiem jednowątkowym, nie chcesz blokować całego serwera! Kod asynchroniczny eliminuje warunki wyścigu, jawnie określając zależności.
Naucz się kochać kod asynchroniczny!
Przyjrzyj się
promises
asynchronicznemu kodowi bez tworzenia piramidy piekła zwrotnego. Polecam bibliotekę promiseQ dla node.jshttp://howtonode.org/promises
EDYCJA: to jest zdecydowanie moja najbardziej kontrowersyjna odpowiedź, węzeł ma teraz słowo kluczowe yield, które pozwala traktować kod asynchroniczny tak, jakby był synchroniczny. http://blog.alexmaccaw.com/how-yield-will-transform-node
źródło