Użyłem Redux-Saga . Kod napisany za jego pomocą jest jak dotąd łatwy do uzasadnienia, poza tym, że funkcja generatora JS od czasu do czasu psuje mi głowę. Z mojego zrozumienia, Redux-Observable może osiągnąć podobną pracę, która obsługuje efekty uboczne, ale bez używania funkcji generatora.
Jednak dokumenty z Redux-Observable nie zawierają wielu opinii na temat tego, dlaczego jest lepszy od Redux-Saga. Chciałbym wiedzieć, czy nie korzystanie z funkcji generatora jest jedyną korzyścią z używania Redux-Observable. A jakie mogą być wady, problemy lub kompromisy wynikające z używania Redux-Observable zamiast Redux-Saga? Z góry dziękuję.
Odpowiedzi:
Zastrzeżenie: Jestem jednym z autorów książki redux-obserwowalnej, więc trudno mi być w 100% bezstronnym.
Obecnie nie podajemy żadnego powodu, dla którego obserwowalna redukcja jest lepsza niż saga redux, ponieważ ... tak nie jest. 😆
tl; dr są wady i zalety obu. Dla wielu jeden jest bardziej intuicyjny niż drugi, ale oba są trudne do nauczenia się na różne sposoby, jeśli nie znasz RxJS (obserwowalny redux) lub generatorów / „efektów jako danych” (saga redux).
Rozwiązują ten sam problem w bardzo podobny sposób, ale mają pewne fundamentalne różnice, które stają się naprawdę widoczne dopiero, gdy użyjesz ich wystarczająco dużo.
obserwowalny redux odkłada prawie wszystko na idiomatyczny RxJS. Więc jeśli masz wiedzę RxJS (lub ją zdobywasz), uczenie się i używanie redux-obserwowalne jest super naturalne. Oznacza to również, że tę wiedzę można przenieść na inne cele niż redukx. Jeśli zdecydujesz się przejść na MobX, jeśli zdecydujesz się przejść na Angular2, jeśli zdecydujesz się przejść na jakąś przyszłą popularność X, są bardzo duże szanse, że RxJS może ci pomóc. Dzieje się tak, ponieważ RxJS jest ogólną biblioteką asynchroniczną i pod wieloma względami przypomina sam język programowania - cały paradygmat „programowania reaktywnego”. RxJS istniał od 2012 roku i zaczynał jako port Rx.NET („porty” są dostępne w prawie każdym głównym języku, jest to przydatne ).
redux-saga zapewnia swoje operatory oparte na czasie, więc chociaż wiedza, którą zdobędziesz na temat generatorów i radzenia sobie z efektami ubocznymi w tym stylu menedżera procesów, jest przenoszalna, rzeczywiste operatory i użycie nie jest używane w żadnej innej dużej bibliotece. To trochę niefortunne, ale z pewnością nie powinno samo w sobie przełamać umowy.
Używa również "efektów jako danych" ( opisanych tutaj ), co może być trudne na początku, ale oznacza to, że kod sagi redux w rzeczywistości sam nie wykonuje efektów ubocznych. Zamiast tego funkcje pomocnicze, których używasz, tworzą obiekty, które są jak zadania, które reprezentują zamiar wywołania efektu ubocznego, a następnie wewnętrzna biblioteka wykonuje go za Ciebie. To sprawia, że testowanie jest niezwykle łatwe, bez potrzeby kpiny i jest bardzo atrakcyjne dla niektórych osób. Jednak osobiście odkryłem, że oznacza to, że twoje testy jednostkowe ponownie zaimplementują większość logiki twojej sagi - co sprawia, że te testy nie są zbyt przydatne IMO (ta opinia nie jest podzielana przez wszystkich)
Ludzie często pytają, dlaczego nie robimy czegoś takiego z obserwowalnymi reduksami: według mnie jest to zasadniczo niekompatybilne z normalnym idiomatycznym Rx. W Rx używamy takich operatorów,
.debounceTime()
które hermetyzują logikę wymaganą do odbicia, ale to oznacza, że jeśli chcieliśmy stworzyć wersję, która nie wykonuje odbicia, a zamiast tego emituje obiekty zadań z zamiarem, straciłeś teraz moc Rx, ponieważ nie można już po prostu łączyć operatorów, ponieważ operowaliby na tym obiekcie zadania, a nie na rzeczywistym wyniku operacji. Naprawdę trudno to elegancko wyjaśnić. Znowu wymaga głębokiego zrozumienia Rx, aby zrozumieć niezgodność podejść. Jeśli naprawdę chcesz czegoś takiego, sprawdź cykle redukcyjnektóry korzysta z cycle.js i głównie ma te cele. Wydaje mi się, że wymaga to zbyt wiele ceremonii jak na mój gust, ale zachęcam do zakręcenia, jeśli Cię to interesuje.Jak wspomniał ThorbenA, nie cofam się przed przyznaniem, że Redux-saga jest obecnie (13.10.16) wyraźnym liderem w złożonym zarządzaniu skutkami ubocznymi reduxu. Został uruchomiony wcześniej i ma bardziej solidną społeczność. Tak więc używanie de facto standardu w stosunku do nowego dzieciaka z bloku jest bardzo atrakcyjne. Myślę, że można bezpiecznie powiedzieć, że jeśli używasz któregokolwiek z nich bez wcześniejszej wiedzy, możesz się trochę pomylić. Obaj używamy dość zaawansowanych koncepcji, które, gdy już się „dostaniesz”, znacznie ułatwiają zarządzanie złożonymi skutkami ubocznymi, ale do tego czasu wielu się potyka.
Najważniejszą radą, jakiej mogę udzielić, jest to, aby nie sprowadzać żadnej z tych bibliotek, zanim będziesz ich potrzebować. Jeśli wykonujesz tylko proste wywołania Ajax, prawdopodobnie ich nie potrzebujesz. redux-thunk jest głupi, łatwy do nauczenia i zapewnia wystarczającą ilość podstaw - ale im bardziej złożona asynchronizacja, tym trudniejsza (lub nawet niemożliwa) staje się dla redux-thunk. Ale w przypadku sagi obserwowalnej przez reduksa pod wieloma względami świeci ona najbardziej, im bardziej złożona jest asynchronizacja. Jest też wiele zalet używania Redux-thunk z jednym z pozostałych (redukx-obserowalne / saga) w tym samym projekcie! redux-thunk dla zwykłych prostych rzeczy, a następnie używając tylko redux-observable / saga do złożonych rzeczy. To świetny sposób na utrzymanie produktywności, więc nie walczysz z obserwowalnymi / sagami reduxu o rzeczy, które byłyby trywialne w przypadku Redux-thunk.
źródło
debounceTime()
„utracie” kontroli nad bardzo ogólną logiką uderzył mnie. Dzięki za wyjaśnienie.Myślę, że są rzeczy, które należy wziąć pod uwagę.
// Redux-Saga import axios from 'axios' function* watchSaga(){ yield takeEvery('fetch_user', fetchUser) // waiting for action (fetch_user) } function* fetchUser(action){ try { yield put({type:'fetch_user_ing'}) const response = yield call(axios.get,'/api/users/1') yield put({type:'fetch_user_done',user:response.data}) } catch (error) { yield put({type:'fetch_user_error',error}) } } // Redux-Observable import axios from 'axios' const fetchUserEpic = action$ => action$ .ofType('fetch_user') .flatMap(()=> Observable.from(axios.get('/api/users/1')) // or use Observable.ajax .map(response=>({type:'fetch_user_done', user:response.data})) .catch(error => Observable.of({type:'fetch_user_error',error})) .startWith({type:'fetch_user_ing'}) )
Napisałem również ten artykuł w celu dokładnego porównania różnic między sagą Redux i Redux-Observable. Sprawdź ten link tutaj lub prezentację .
źródło
Używam Redux-Observable zamiast Redux-Saga, ponieważ wolę pracować z obserwowalnymi niż generatorami. Używam go z RXJS, która jest potężną biblioteką do pracy ze strumieniami danych. Pomyśl o tym jak o lodash dla async. Jeśli chodzi o wszelkie wady, problemy i kompromisy w wyborze jednego z nich, spójrz na tę odpowiedź Jaya Phelpsa:
źródło
Redux-Observable to niesamowita biblioteka, używamy jej w produkcji przez 1,5 roku bez żadnych problemów do tej pory, jest doskonale testowalna i można ją łatwo zintegrować z dowolnym frameworkiem. Mamy ekstremalnie przeciążone równoległe kanały gniazd, a jedyną rzeczą, która chroni nas przed zawieszeniami, jest obserwowalna redux
Chciałbym tu wspomnieć o 3 punktach.
1. Złożoność i krzywa uczenia się
Saga Redux z łatwością bije tutaj redukcję, którą można zaobserwować. Jeśli potrzebujesz tylko prostego wniosku, aby uzyskać autoryzację, a nie chcesz używać redux-thunk z jakichś powodów, powinieneś rozważyć użycie redux-saga, jest to po prostu łatwiejsze do zrozumienia.
Jeśli nie masz wcześniejszej wiedzy na temat Observable, będzie to dla ciebie uciążliwe, a twój zespół cię oprowadzi :)
2. Co może mi zaoferować Observable i RxJS?
Jeśli chodzi o logikę asynchroniczną, Observable to twój szwajcarski nóż, Observable może zrobić za Ciebie dosłownie wszystko. Nigdy nie powinieneś porównywać ich z obietnicami lub generatorami, który jest znacznie mocniejszy, to tak samo, jak porównanie Optimusa Prime z Chevroletem.
A co z RxJS? To jest jak lodash.js, ale dla logiki asynchronicznej, kiedy już wejdziesz, nigdy nie przełączysz się na coś innego.
3. Rozszerzenie reaktywne
Po prostu sprawdź ten link
Rozszerzenie reaktywne jest zaimplementowane dla wszystkich nowoczesnych języków programowania, to tylko Twój klucz do programowania funkcjonalnego.
Spędź więc czas mądrze, ucz się RxJS i używaj redux-obserwa- calne
źródło
Cenię możliwość przenoszenia między językami i środowiskami wykonawczymi, które ma Rx. Nawet jeśli Twoja aplikacja nie zmieni języka, Twoja kariera może. Zdobądź najlepszą możliwą dźwignię w nauce, bez względu na to, jak oceniasz to dla siebie. W szczególności jest to świetna brama do .Net LINQ.
źródło
Ponieważ jest tu cała masa rozmów, które można zaobserwować w reduksie, pomyślałem, że przedstawię sagę argumentacji. Nie używam obserwowalnych reduxów ani RxJS, więc nie mogę dać porównania obok siebie, ale użyłem sagi z doskonałym efektem.
Na ile to warte, używam sag w produkcji w aplikacji internetowej.
Sagas kontra Thunk
Saga wygrywa. Nie podobało mi się, jak Thunk umieścił logikę w moich twórcach akcji. Sprawiało to również, że wykonanie kilku żądań z rzędu było kłopotliwe. Krótko przyjrzałem się temu, co można zaobserwować w tej pracy, ale zdecydowałem się na Sagas.
Krzywa uczenia się dla sag
Zrozumienie, czym są generatory i dlaczego są ważne, jest kluczem do zrozumienia sag. Ale podkreślę, że nie musisz znać generatorów od podszewki. Musisz tylko wiedzieć, że przekazujesz kontrolę za pomocą instrukcji yield i że saga przekaże kontrolę z powrotem po rozwiązaniu kodu asynchronicznego. Po tym kawałku nietrudno jest zrozumieć, co dzieje się w sadze.
Podstawowe metody sagi to (z mojego doświadczenia):
call
- Wywołaj dowolny fragment kodu i uzyskaj wartość zwracaną. Obsługuje obietnice. Świetna synergia między przetwarzaniem asynchronicznym i sagami.select
- Zadzwoń do selektora. Ten kawałek jest raczej genialny. Selektory są kluczowe dla Redux i są w 100% obsługiwane!put
- akadispatch
akcja. W rzeczywistości wyślij tyle, ile chcesz!Są inne funkcje, ale jeśli opanujesz te trzy, będziesz w naprawdę dobrym miejscu.
Wniosek
Powodem, dla którego wybrałem sagi, była łatwość obsługi. obserwowalne w reduksie wyglądało na wyzwanie. Jestem w 100% zadowolony z sag. Bardziej szczęśliwy, niż się spodziewałem.
Z mojego doświadczenia wynika, że Sagi są (o wiele) lepsze niż bzdury i stosunkowo łatwe do zrozumienia. Rx nie jest filiżanką herbaty dla każdego. Zdecydowanie rozważałbym sagi zamiast obserwowalnych reduxów, jeśli nie pochodzisz z tego ekosystemu i / lub nie planujesz używać Rx w przyszłości.
źródło
Jeśli piszesz swoją aplikację w Typescript, polecam sprawdzenie bez typu . Jest inspirowany Redux-Observable, a także zależy od RxJS, ale istnieje cały ekosystem do tworzenia aplikacji.
Największą wadą sagi, którą można zaobserwować / zredukować, jest brak wytycznych. Nie ma oficjalnych wytycznych dotyczących leniwego zmniejszania obciążenia, sag lub eposów. Podział kodu jest krytyczny podczas skalowania większych aplikacji. Niestandardowe rozwiązania do leniwego ładowania zwykle nie działają z HMR, co powoduje złe doświadczenia programistów.
Beztypowe plusy:
Wszystkie interfejsy API są zaprojektowane pod kątem maszynopisu i bezpieczeństwa typów:
Sprawdź https://typeless.js.org/
źródło