Właśnie zacząłem używać węzła i jedną z rzeczy, które szybko zauważyłem, jest szybkość wywołań zwrotnych do głupiego poziomu wcięcia:
doStuff(arg1, arg2, function(err, result) {
doMoreStuff(arg3, arg4, function(err, result) {
doEvenMoreStuff(arg5, arg6, function(err, result) {
omgHowDidIGetHere();
});
});
});
Oficjalny przewodnik styl mówi umieścić każdy zwrotnego w osobnej funkcji, ale to wydaje się zbyt restrykcyjne w sprawie stosowania zamknięć, a co pojedynczy obiekt zadeklarowane w poziomie górnym dostępnych kilka warstw w dół, a obiekt ma być przekazany przez cały pośrednie wywołania zwrotne.
Czy można w tym celu skorzystać z zakresu funkcji? Umieścić wszystkie funkcje zwrotne, które potrzebują dostępu do obiektu globalnego, w funkcji, która deklaruje ten obiekt, więc przechodzi do zamknięcia?
function topLevelFunction(globalishObject, callback) {
function doMoreStuffImpl(err, result) {
doMoreStuff(arg5, arg6, function(err, result) {
callback(null, globalishObject);
});
}
doStuff(arg1, arg2, doMoreStuffImpl);
}
i tak dalej przez kilka kolejnych warstw ...
A może istnieją ramy itp., Które pomagają zmniejszyć poziomy wcięć bez deklarowania nazwanej funkcji dla każdego pojedynczego wywołania zwrotnego? Jak sobie radzisz z piramidą oddzwaniania?
źródło
Odpowiedzi:
Istnieje wiele wdrożeń „obietnic”:
Na przykład możesz przepisać zagnieżdżone wywołania zwrotne
lubić
Zamiast oddzwaniania w oddzwanianiu
a(b(c()))
łączysz łańcuch „.then”a().then(b()).then(c())
.Wprowadzenie tutaj: http://howtonode.org/promises
źródło
Jako alternatywę dla obietnic powinieneś przyjrzeć się
yield
słowu kluczowemu w połączeniu z funkcjami generatora, które zostaną wprowadzone w EcmaScript 6. Oba są dostępne dzisiaj w kompilacjach Node.js 0.11.x, ale wymagają dodatkowo określenia--harmony
flagi podczas uruchamiania Node .js:Stosując te konstrukty i biblioteki takie jak TJ Holowaychuk za co pozwala na pisanie kodu asynchronicznego w stylu, który wygląda jak kod synchronicznym, chociaż nadal działa w sposób asynchroniczny. Zasadniczo te rzeczy razem implementują wspólną obsługę Node.js.
Zasadniczo, musisz napisać funkcję generatora kodu, który uruchamia rzeczy asynchroniczne, wywołać tam rzeczy asynchroniczne, ale poprzedzić je
yield
słowem kluczowym. W końcu twój kod wygląda następująco:Aby uruchomić tę funkcję generatora, potrzebujesz biblioteki takiej jak wspomniana wcześniej co. Połączenie wygląda wtedy następująco:
Lub, mówiąc wprost:
Należy pamiętać, że z funkcji generatora można wywoływać inne funkcje generatora, wystarczy tylko
yield
ponownie je poprzedzić .Aby uzyskać wprowadzenie do tego tematu, wyszukaj w Google hasła takie jak
yield generators es6 async nodejs
i powinieneś znaleźć mnóstwo informacji. Przyzwyczajenie się do tego zajmuje trochę czasu, ale kiedy już go dostaniesz, nie chcesz wracać.Należy pamiętać, że nie tylko zapewnia to lepszą składnię do wywoływania funkcji, ale także pozwala korzystać ze zwykłych (synchronicznych) elementów logiki przepływu sterowania, takich jak
for
pętle lubtry
/catch
. Nigdy więcej bałaganu z wieloma oddzwanianiami i wszystkimi tymi rzeczami.Powodzenia i miłej zabawy :-)!
źródło
Masz teraz pakiet asyncawait z bardzo ścisłą składnią do tego, co powinno być przyszłym rodzimym wsparciem dla
await
&async
in Node.Zasadniczo pozwala na pisanie kodu asynchronicznego wyglądającego synchronicznie , znacznie zmniejszając poziomy LOC i wcięcia, z kompromisem niewielkiej utraty wydajności (liczby właścicieli pakietów są 79% prędkości w porównaniu do nieprzetworzonych wywołań zwrotnych), miejmy nadzieję, że zmniejszony, gdy dostępna będzie obsługa natywna.
Nadal dobry wybór, aby wydostać się z oddzwaniania piekło / piramida koszmaru zagłady IMO, gdy wydajność nie jest najważniejsza i gdzie synchroniczny styl pisania lepiej odpowiada potrzebom projektu.
Podstawowy przykład z pakietu doc:
źródło