Mam uproszczoną funkcję, która wygląda następująco:
function(query) {
myApi.exec('SomeCommand', function(response) {
return response;
});
}
Zasadniczo chcę, aby zadzwonił myApi.exec
i zwrócił odpowiedź podaną w wywołaniu zwrotnym lambda. Jednak powyższy kod nie działa i po prostu zwraca natychmiast.
Tylko dla bardzo hackerskiej próby wypróbowałem poniższe, które nie działały, ale przynajmniej masz pojęcie, co próbuję osiągnąć:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
while (!r) {}
return r;
}
Zasadniczo, co jest dobrym sposobem na osiągnięcie tego? Chcę, aby moja funkcja czekała na wywołanie wywołania zwrotnego, a następnie zwraca wartość, która została do niej przekazana.
Odpowiedzi:
„Dobrym sterowaniem opartym na zdarzeniach node.js / event” jest nie czekać .
Podobnie jak prawie wszystko inne podczas pracy z systemami sterowanymi zdarzeniami, takimi jak węzeł, twoja funkcja powinna zaakceptować parametr wywołania zwrotnego, który zostanie wywołany po zakończeniu obliczeń. Osoba dzwoniąca nie powinna czekać na „zwrócenie” wartości w normalnym sensie, ale raczej wysłać procedurę, która będzie obsługiwała wynikową wartość:
Więc nie używaj go w ten sposób:
Ale tak:
źródło
fs
sync*
metody). W związku z tym uważam, że to wciąż ważne pytanie. Czy jest jakiś dobry sposób na uzyskanie blokowania w węźle oprócz zajętego oczekiwania?sync
metody. (2) Użyj włókien, github.com/laverdet/node-fibers , (3) Użyj obietnic, na przykład biblioteki Q, (4) Użyj cienkiej warstwy na javascript, która wygląda na blokującą, ale kompiluje się w celu asynchronizacji, jak maxtaco.github.com/coffee-scriptJednym ze sposobów osiągnięcia tego jest zawinięcie wywołania interfejsu API w obietnicę, a następnie użycie go w
await
celu oczekiwania na wynik.Wynik:
źródło
async/await
Nie potrzebuję tego często, więc mam problemy z zapamiętywaniem, jak sobie z tym poradzić, kopiuję to dla moich osobistych notatek / referencji.sprawdź to: https://github.com/luciotato/waitfor-ES6
twój kod z wait.for: (wymaga generatorów, --harmony flag)
źródło
Jeśli nie chcesz korzystać z oddzwaniania, możesz użyć modułu „Q”.
Na przykład:
Aby uzyskać więcej informacji, patrz: https://github.com/kriskowal/q
źródło
Jeśli chcesz, aby było to bardzo proste i łatwe, bez fantazyjnych bibliotek, czekanie na wykonanie funkcji zwrotnych w węźle przed wykonaniem innego kodu wygląda następująco:
źródło
Uwaga: prawdopodobnie nie należy używać tej odpowiedzi w kodzie produkcyjnym. To hack i powinieneś wiedzieć o implikacjach.
Istnieje uvrun moduł (zaktualizowane do nowszych wersji Nodejs tutaj ), gdzie można wykonać jedną rundę pętli na libuv głównej pętli zdarzeń (co jest Nodejs głównym pętla).
Twój kod wyglądałby tak:
(Możesz użyć alternatywnie
uvrun.runNoWait()
. Pozwoli to uniknąć problemów z blokowaniem, ale zajmie 100% procesora.)Zauważ, że takie podejście unieważnia cały cel Nodejsa, tj. Aby wszystko było asynchroniczne i nieblokujące. Może to również znacznie zwiększyć głębokość stosu wywołań, co może spowodować przepełnienie stosu. Jeśli uruchomisz taką funkcję rekurencyjnie, na pewno napotkasz problemy.
Zobacz inne odpowiedzi na temat przeprojektowania kodu, aby zrobić to „dobrze”.
To rozwiązanie tutaj jest prawdopodobnie przydatne tylko podczas testowania i esp. chcę mieć zsynchronizowany i seryjny kod.
źródło
Od węzła 4.8.0 możesz korzystać z funkcji ES6 zwanej generatorem. Możesz zapoznać się z tym artykułem, aby uzyskać więcej informacji. Ale w zasadzie możesz użyć generatorów i obietnic, aby wykonać tę pracę. Używam Bluebird do promisify i zarządzać generator.
Twój kod powinien być w porządku, tak jak w przykładzie poniżej.
źródło
zakładając, że masz funkcję:
możesz skorzystać z takich wywołań zwrotnych:
źródło
To przeczy celowi nieblokowania IO - blokujesz go, gdy nie wymaga blokowania
:)
Powinieneś zagnieździć swoje wywołania zwrotne zamiast zmuszać node.js do czekania lub wywołać inne wywołanie zwrotne wewnątrz wywołania zwrotnego, w którym potrzebujesz wyniku
r
.Możliwe, że jeśli musisz wymusić blokowanie, źle myślisz o swojej architekturze.
źródło
http.get()
jakiegoś adresu URL iconsole.log()
jego zawartości. Dlaczego muszę przeskakiwać wstecz, aby to zrobić w Węźle?Korzystanie z asynchronizacji i czekania jest o wiele łatwiejsze.
źródło