Jaki jest prawidłowy sposób obsługi błędów w strumieniach? Wiem już, że istnieje zdarzenie „błąd”, którego można słuchać, ale chcę poznać więcej szczegółów na temat dowolnie skomplikowanych sytuacji.
Na początek, co robisz, gdy chcesz zrobić prosty łańcuch rur:
input.pipe(transformA).pipe(transformB).pipe(transformC)...
Jak poprawnie utworzyć jedną z tych transformacji, aby błędy były poprawnie obsługiwane?
Więcej powiązanych pytań:
- kiedy wystąpi błąd, co dzieje się ze zdarzeniem „koniec”? Czy nigdy się nie strzela? Czy czasami się strzela? Czy to zależy od transformacji / strumienia? Jakie są tutaj standardy?
- czy są jakieś mechanizmy rozsyłania błędów przez rury?
- czy domeny skutecznie rozwiązują ten problem? Przykłady byłyby fajne.
- czy błędy wynikające ze zdarzeń „error” mają ślady stosu? Czasami? Nigdy? czy jest sposób, aby je od nich zdobyć?
Promise
frameworki czynią to o wiele prostszymOdpowiedzi:
przekształcać
Strumienie transformacji są zarówno czytelne, jak i zapisywalne, a zatem są naprawdę dobrymi strumieniami „środkowymi”. Z tego powodu czasami nazywa się je
through
strumieniami. W ten sposób są podobne do strumienia dupleksowego, z wyjątkiem tego, że zapewniają przyjemny interfejs do manipulowania danymi, a nie tylko ich wysyłania. Celem strumienia transformacji jest manipulowanie danymi podczas przesyłania ich przez strumień. Możesz na przykład chcieć wykonać kilka wywołań asynchronicznych lub wyprowadzić kilka pól, zmienić mapowanie niektórych rzeczy itp.Aby dowiedzieć się, jak utworzyć strumień transformacji, zobacz tutaj i tutaj . Wszystko co musisz zrobić to :
_transform
metodę, która przyjmuje plik(chunk, encoding, callback)
.Kawałek to twoje dane. W większości przypadków nie musisz martwić się o kodowanie, jeśli pracujesz w programie
objectMode = true
. Wywołanie zwrotne jest wywoływane po zakończeniu przetwarzania porcji. Ten fragment jest następnie wypychany do następnego strumienia.Jeśli potrzebujesz fajnego modułu pomocniczego, który pozwoli ci naprawdę łatwo przejść przez stream, proponuję przez through2 .
Aby uzyskać informacje na temat obsługi błędów, czytaj dalej.
rura
W łańcuchu potoków błędy obsługi są rzeczywiście nietrywialne. Zgodnie z tym wątkiem .pipe () nie jest zbudowany do przekazywania błędów. Więc coś w stylu ...
... nasłuchiwał tylko błędów w strumieniu
c
. Gdyby wyemitowano zdarzenie błędua
, nie zostałoby ono przekazane, a faktycznie zostałoby odrzucone. Aby zrobić to poprawnie:Teraz, chociaż drugi sposób jest bardziej szczegółowy, możesz przynajmniej zachować kontekst, w którym występują błędy. Zwykle jest to dobra rzecz.
Jedna biblioteka, którą uważam za pomocną, jeśli masz przypadek, w którym chcesz uchwycić tylko błędy w miejscu docelowym i nie obchodzi Cię tak bardzo, gdzie to się stało, to strumień zdarzeń .
koniec
Gdy zostanie wyzwolone zdarzenie błędu, zdarzenie końcowe nie zostanie uruchomione (jawnie). Emisja zdarzenia błędu zakończy transmisję.
domeny
Z mojego doświadczenia wynika, że domeny działają bardzo dobrze przez większość czasu. Jeśli masz nieobsłużone zdarzenie błędu (np. Emitowanie błędu w strumieniu bez nasłuchiwania), serwer może ulec awarii. Teraz, jak wskazuje powyższy artykuł, możesz umieścić strumień w domenie, która powinna poprawnie wychwycić wszystkie błędy.
Piękno domen polega na tym, że zachowują ślady stosu. Chociaż strumień wydarzeń również dobrze sobie z tym radzi.
Aby uzyskać więcej informacji, zapoznaj się z podręcznikiem transmisji strumieniowej . Całkiem dogłębne, ale bardzo przydatne i zawiera świetne linki do wielu pomocnych modułów.
źródło
.on('error')
a.on('error', function(e){handleError(e)})
a.on('error', handleError)
Jeśli używasz node> = v10.0.0, możesz użyć stream.pipeline i stream.finished .
Na przykład:
Więcej dyskusji znajdziesz w tym PR na githubie.
źródło
finished
, skoropipeline
już masz oddzwonienie?domeny są przestarzałe. nie potrzebujesz ich.
w przypadku tego pytania rozróżnienie między przekształcaniem a zapisywalnością nie jest tak ważne.
Odpowiedź mshell_lauren jest świetna, ale alternatywnie możesz również wyraźnie nasłuchiwać zdarzenia błędu w każdym strumieniu, który Twoim zdaniem może powodować błąd. i jeśli wolisz, użyj ponownie funkcji obsługi.
Dzięki temu unikniesz niesławnego, nieprzechwyconego wyjątku, jeśli jeden z tych strumieni uruchomi zdarzenie błędu
źródło
error
równie dobrze można wtedy poprzestać na tym, że każde zdarzenie jest odrębne; 2) Jakie biblioteki strumieniowe są napisane powyżej, poza natywną funkcjonalnością Node.js? i 3) dlaczego ma znaczenie, w jaki sposób obsługują zdarzenia wewnętrznie, skoro to oczywiście pozwala każdemu na dołączenie dodatkowych modułów obsługi błędów do tego, co już istnieje?Błędy z całego łańcucha można propagować do strumienia znajdującego się najbardziej po prawej stronie za pomocą prostej funkcji:
które mogą być używane jak:
źródło
.on("error", handler)
zajmuje się tylko błędami Stream, ale jeśli używasz niestandardowych strumieni Transform,.on("error", handler)
nie wychwytuj błędów występujących w_transform
funkcji. Więc można zrobić coś takiego, aby kontrolować przepływ aplikacji: -this
słowo kluczowe w_transform
funkcji odnosi się doStream
samego siebie, czyli plikuEventEmitter
. Możesz więc użyćtry catch
jak poniżej, aby wyłapać błędy, a następnie przekazać je do niestandardowych programów obsługi zdarzeń.W ten sposób możesz oddzielić logikę i programy obsługi błędów. Możesz też zdecydować się na obsługę tylko niektórych błędów, a ignorowanie innych.
UPDATE
Alternative: RXJS Observable
źródło
Użyj pakietu multipipe , aby połączyć kilka strumieni w jeden strumień dupleksowy. I obsługuj błędy w jednym miejscu.
źródło
Użyj wzorca Node.js, tworząc mechanikę strumienia Transform i wywołując jej wywołanie zwrotne
done
z argumentem, aby propagować błąd:źródło
Funkcja Try catch nie przechwyci błędów, które wystąpiły w strumieniu, ponieważ są one zgłaszane po zakończeniu działania kodu wywołującego. możesz zapoznać się z dokumentacją:
https://nodejs.org/dist/latest-v10.x/docs/api/errors.html
źródło