Ένας αρχάριος οδηγός για RxJS & Redux παρατηρήσιμο

Το Redux-Observable είναι ένα ενδιάμεσο λογισμικό βασισμένο σε RxJS για το Redux που επιτρέπει στους προγραμματιστές να συνεργάζονται με ενέργειες ασύγχυσης. Είναι μια εναλλακτική λύση για το redux-thunk και το redux-saga.

Αυτό το άρθρο καλύπτει τα βασικά του RxJS, τον τρόπο ρύθμισης του Redux-Observables και μερικές από τις πρακτικές περιπτώσεις χρήσης του. Αλλά πριν από αυτό, πρέπει να κατανοήσουμε το Πρόγραμμα Παρατηρητών .

Σχέδιο παρατηρητή

Στο σχέδιο Observer, ένα αντικείμενο που ονομάζεται "Παρατηρήσιμο" ή "Θέμα", διατηρεί μια συλλογή συνδρομητών που ονομάζεται "Παρατηρητές". Όταν η κατάσταση των θεμάτων αλλάζει, ειδοποιεί όλους τους παρατηρητές της.

Στο JavaScript, το απλούστερο παράδειγμα θα ήταν οι εκδότες συμβάντων και οι διαχειριστές συμβάντων.

Όταν το κάνετε .addEventListener, πιέζετε έναν παρατηρητή στη συλλογή παρατηρητών του θέματος. Κάθε φορά που συμβαίνει το συμβάν, το θέμα ειδοποιεί όλους τους παρατηρητές.

RxJS

Σύμφωνα με τον επίσημο ιστότοπο,

Το RxJS είναι υλοποίηση JavaScript του ReactiveX, μιας βιβλιοθήκης για τη σύνθεση ασύγχρονων προγραμμάτων βάσει συμβάντων χρησιμοποιώντας παρατηρήσιμες ακολουθίες.

Με απλά λόγια, το RxJS είναι μια εφαρμογή του μοτίβου Observer. Επεκτείνει επίσης το μοτίβο Observer παρέχοντας τελεστές που μας επιτρέπουν να συνθέσουμε Παρατηρήσιμα και Θέματα με δηλωτικό τρόπο.

Οι παρατηρητές, τα παρατηρήσιμα, οι χειριστές και τα θέματα είναι τα δομικά στοιχεία του RxJS. Ας δούμε λοιπόν τον καθένα με περισσότερες λεπτομέρειες τώρα.

Παρατηρητές

Οι παρατηρητές είναι αντικείμενα που μπορούν να εγγραφούν στα Παρατηρήσιμα και Θέματα. Μετά την εγγραφή τους, μπορούν να λαμβάνουν ειδοποιήσεις τριών τύπων - επόμενο, σφάλμα και πλήρες.

Οποιοδήποτε αντικείμενο με την ακόλουθη δομή μπορεί να χρησιμοποιηθεί ως Παρατηρητής.

interface Observer { closed?: boolean; next: (value: T) => void; error: (err: any) => void; complete: () => void; }

Όταν το παρατηρήσιμο ωθεί την επόμενη, λάθος, και πλήρεις κοινοποιήσεις, του παρατηρητή .next, .errorκαι .completeγίνεται επίκληση μεθόδους.

Παρατηρήσιμα

Τα παρατηρήσιμα είναι αντικείμενα που μπορούν να εκπέμπουν δεδομένα για μια χρονική περίοδο. Μπορεί να αναπαρασταθεί χρησιμοποιώντας το "μαρμάρινο διάγραμμα".

Όπου η οριζόντια γραμμή αντιπροσωπεύει το χρόνο, οι κυκλικοί κόμβοι αντιπροσωπεύουν τα δεδομένα που εκπέμπονται από το Παρατηρήσιμο και η κατακόρυφη γραμμή δείχνει ότι το Παρατηρήσιμο έχει ολοκληρωθεί με επιτυχία.

Τα παρατηρήσιμα ενδέχεται να παρουσιάσουν σφάλμα. Ο σταυρός αντιπροσωπεύει το σφάλμα που εκπέμπεται από το παρατηρήσιμο.

Οι καταστάσεις "ολοκληρώθηκε" και "σφάλμα" είναι οριστικές. Αυτό σημαίνει ότι τα παρατηρήσιμα δεν μπορούν να εκπέμπουν δεδομένα αφού ολοκληρώσουν επιτυχώς ή αντιμετώπισαν σφάλμα.

Δημιουργία ενός παρατηρήσιμου

Τα παρατηρήσιμα δημιουργούνται χρησιμοποιώντας τον new Observableκατασκευαστή που παίρνει ένα όρισμα - τη συνδρομή Παρατηρήσιμα μπορούν επίσης να δημιουργηθούν χρησιμοποιώντας ορισμένους χειριστές, αλλά θα το συζητήσουμε αργότερα όταν μιλάμε για χειριστές.

import { Observable } from 'rxjs'; const observable = new Observable(subscriber => { // Subscribe function });

Εγγραφή σε παρατηρήσιμο

Τα παρατηρήσιμα μπορούν να εγγραφούν χρησιμοποιώντας τη .subscribeμέθοδο τους και να περάσουν έναν Παρατηρητή.

observable.subscribe({ next: (x) => console.log(x), error: (x) => console.log(x), complete: () => console.log('completed'); });

Εκτέλεση ενός παρατηρήσιμου

Η συνδρομή συνδρομής που μεταβιβάσαμε στον new Observableκατασκευαστή εκτελείται κάθε φορά που εγγράφεται το Observable.

Η συνδρομητική συνάρτηση παίρνει ένα όρισμα - τον Συνδρομητή. Ο Συνδρομητής μοιάζει με τη δομή του παρατηρητή, και έχει τα ίδια 3 μεθόδους: .next, .error, και .complete.

Τα παρατηρήσιμα μπορούν να ωθήσουν δεδομένα στον Παρατηρητή χρησιμοποιώντας τη .nextμέθοδο. Εάν το Observable έχει ολοκληρωθεί με επιτυχία, μπορεί να ειδοποιήσει τον Observer χρησιμοποιώντας τη .completeμέθοδο. Εάν το Παρατηρήσιμο αντιμετώπισε σφάλμα, μπορεί να προωθήσει το σφάλμα στον Παρατηρητή χρησιμοποιώντας τη .errorμέθοδο.

// Create an Observable const observable = new Observable(subscriber => { subscriber.next('first data'); subscriber.next('second data'); setTimeout(() => { subscriber.next('after 1 second - last data'); subscriber.complete(); subscriber.next('data after completion'); //  console.log(x), error: (x) => console.log(x), complete: () => console.log('completed') }); // Outputs: // // first data // second data // third data // after 1 second - last data // completed

Τα παρατηρήσιμα είναι η Unicast

Τα παρατηρήσιμα είναι unicast , πράγμα που σημαίνει ότι τα παρατηρήσιμα μπορούν να έχουν το πολύ έναν συνδρομητή. Όταν ένας Παρατηρητής εγγραφεί σε ένα Παρατηρήσιμο, λαμβάνει ένα αντίγραφο του Παρατηρήσιμου που έχει τη δική του διαδρομή εκτέλεσης, καθιστώντας τα Παρατηρήσιμα unicast.

Είναι σαν να παρακολουθείτε ένα βίντεο στο YouTube. Όλοι οι θεατές παρακολουθούν το ίδιο περιεχόμενο βίντεο, αλλά, μπορούν να παρακολουθούν διαφορετικά τμήματα του βίντεο.

Παράδειγμα : ας δημιουργήσουμε ένα παρατηρήσιμο που εκπέμπει 1 έως 10 σε 10 δευτερόλεπτα. Στη συνέχεια, εγγραφείτε στο παρατηρήσιμο μία φορά αμέσως και ξανά μετά από 5 δευτερόλεπτα.

// Create an Observable that emits data every second for 10 seconds const observable = new Observable(subscriber => { let count = 1; const interval = setInterval(() => { subscriber.next(count++); if (count > 10) { clearInterval(interval); } }, 1000); }); // Subscribe to the Observable observable.subscribe({ next: value => { console.log(`Observer 1: ${value}`); } }); // After 5 seconds subscribe again setTimeout(() => { observable.subscribe({ next: value => { console.log(`Observer 2: ${value}`); } }); }, 5000); /* Output Observer 1: 1 Observer 1: 2 Observer 1: 3 Observer 1: 4 Observer 1: 5 Observer 2: 1 Observer 1: 6 Observer 2: 2 Observer 1: 7 Observer 2: 3 Observer 1: 8 Observer 2: 4 Observer 1: 9 Observer 2: 5 Observer 1: 10 Observer 2: 6 Observer 2: 7 Observer 2: 8 Observer 2: 9 Observer 2: 10 */

Στην έξοδο, μπορείτε να παρατηρήσετε ότι ο δεύτερος Observer ξεκίνησε την εκτύπωση από το 1, παρόλο που έγινε εγγραφή μετά από 5 δευτερόλεπτα. Αυτό συμβαίνει επειδή ο δεύτερος Παρατηρητής έλαβε ένα αντίγραφο του Παρατηρήσιμου του οποίου κλήθηκε ξανά η συνδρομή. Αυτό απεικονίζει τη unicast συμπεριφορά των Παρατηρήσιμων.

μαθήματα

Ένα Θέμα είναι ένας ειδικός τύπος Παρατηρήσιμου.

Δημιουργία θέματος

Ένα Θέμα δημιουργείται χρησιμοποιώντας τον new Subjectκατασκευαστή.

import { Subject } from 'rxjs'; // Create a subject const subject = new Subject();

Εγγραφή σε Θέμα

Η εγγραφή σε ένα Θέμα είναι παρόμοια με την εγγραφή σε ένα Παρατηρήσιμο: χρησιμοποιείτε τη .subscribeμέθοδο και περνάτε έναν Παρατηρητή.

subject.subscribe({ next: (x) => console.log(x), error: (x) => console.log(x), complete: () => console.log("done") });

Εκτέλεση ενός θέματος

Σε αντίθεση με Παρατηρήσημα, ένα θέμα απαιτεί τη δική του .next, .errorκαι .completeμεθόδους για να ωθήσει τα δεδομένα των παρατηρητών.

// Push data to all observers subject.next('first data'); // Push error to all observers subject.error('oops something went wrong'); // Complete subject.complete('done');

Τα θέματα είναι Multicast

Τα θέματα είναι πολλαπλής μετάδοσης: πολλοί παρατηρητές μοιράζονται το ίδιο Θέμα και τη διαδρομή εκτέλεσης. Αυτό σημαίνει ότι όλες οι ειδοποιήσεις μεταδίδονται σε όλους τους Παρατηρητές. Είναι σαν να παρακολουθείτε ένα ζωντανό πρόγραμμα. Όλοι οι θεατές παρακολουθούν το ίδιο τμήμα του ίδιου περιεχομένου ταυτόχρονα.

Παράδειγμα: ας δημιουργήσουμε ένα Θέμα που εκπέμπει 1 έως 10 σε 10 δευτερόλεπτα. Στη συνέχεια, εγγραφείτε στο παρατηρήσιμο μία φορά αμέσως και ξανά μετά από 5 δευτερόλεπτα.

// Create a subject const subject = new Subject(); let count = 1; const interval = setInterval(() => { subscriber.next(count++); if (count > 10) { clearInterval(interval); } }, 1000); // Subscribe to the subjects subject.subscribe(data => { console.log(`Observer 1: ${data}`); }); // After 5 seconds subscribe again setTimeout(() => { subject.subscribe(data => { console.log(`Observer 2: ${data}`); }); }, 5000); /* OUTPUT Observer 1: 1 Observer 1: 2 Observer 1: 3 Observer 1: 4 Observer 1: 5 Observer 2: 5 Observer 1: 6 Observer 2: 6 Observer 1: 7 Observer 2: 7 Observer 1: 8 Observer 2: 8 Observer 1: 9 Observer 2: 9 Observer 1: 10 Observer 2: 10 */ 

Στην έξοδο, μπορείτε να παρατηρήσετε ότι ο δεύτερος Observer ξεκίνησε την εκτύπωση από 5 αντί να ξεκινά από το 1. Αυτό συμβαίνει επειδή ο δεύτερος Observer μοιράζεται το ίδιο Θέμα. Δεδομένου ότι έχει εγγραφεί μετά από 5 δευτερόλεπτα, το Θέμα έχει ήδη ολοκληρώσει την εκπομπή 1 έως 4. Αυτό δείχνει τη συμπεριφορά πολλαπλής διανομής ενός Θέματος.

Τα θέματα είναι τόσο Παρατηρήσιμα όσο και Παρατηρητής

Τα θέματα έχουν το .next, .errorκαι τις .completeμεθόδους. Αυτό σημαίνει ότι ακολουθούν τη δομή των Παρατηρητών. Ως εκ τούτου, ένα Θέμα μπορεί επίσης να χρησιμοποιηθεί ως Παρατηρητής και να περάσει στη .subscribeλειτουργία Παρατηρήσιμων ή άλλων Θεμάτων.

Παράδειγμα: ας δημιουργήσουμε ένα παρατηρήσιμο και ένα θέμα. Στη συνέχεια εγγραφείτε στο Παρατηρήσιμο χρησιμοποιώντας το Θέμα ως Παρατηρητής. Τέλος, εγγραφείτε στο Θέμα. Όλες οι τιμές που εκπέμπονται από το Παρατηρήσιμο θα προωθηθούν στο Θέμα και το Θέμα θα μεταδώσει τις ληφθείσες τιμές σε όλους τους Παρατηρητές του.

// Create an Observable that emits data every second const observable = new Observable(subscriber => { let count = 1; const interval = setInterval(() => { subscriber.next(count++); if (count > 5) { clearInterval(interval); } }, 1000); }); // Create a subject const subject = new Subject(); // Use the Subject as Observer and subscribe to the Observable observable.subscribe(subject); // Subscribe to the subject subject.subscribe({ next: value => console.log(value) }); /* Output 1 2 3 4 5 */

Χειριστές

Οι χειριστές είναι αυτό που κάνουν το RxJS χρήσιμο. Οι χειριστές είναι καθαρές λειτουργίες που επιστρέφουν ένα νέο παρατηρήσιμο. Μπορούν να ταξινομηθούν σε 2 κύριες κατηγορίες:

  1. Χειριστές Δημιουργίας
  2. Χειριστές με σωλήνωση

Χειριστές Δημιουργίας

Οι δημιουργοί δημιουργίας είναι λειτουργίες που μπορούν να δημιουργήσουν ένα νέο παρατηρήσιμο.

Παράδειγμα: μπορούμε να δημιουργήσουμε ένα παρατηρήσιμο που εκπέμπει κάθε στοιχείο ενός πίνακα χρησιμοποιώντας τον fromτελεστή.

const observable = from([2, 30, 5, 22, 60, 1]); observable.subscribe({ next: (value) => console.log("Received", value), error: (err) => console.log(err), complete: () => console.log("done") }); /* OUTPUTS Received 2 Received 30 Received 5 Received 22 Received 60 Received 1 done */

Το ίδιο μπορεί να είναι ένα παρατηρήσιμο χρησιμοποιώντας το μαρμάρινο διάγραμμα.

Χειριστές με σωλήνωση

Οι Pipeable Operators είναι λειτουργίες που λαμβάνουν ένα παρατηρήσιμο ως είσοδος και επιστρέφουν ένα νέο παρατηρήσιμο με τροποποιημένη συμπεριφορά

Παράδειγμα: ας πάρουμε το παρατηρήσιμο που δημιουργήσαμε χρησιμοποιώντας τον fromτελεστή. Τώρα χρησιμοποιώντας αυτό το παρατηρήσιμο, μπορούμε να δημιουργήσουμε ένα νέο παρατηρήσιμο που εκπέμπει μόνο αριθμούς μεγαλύτερους από 10 χρησιμοποιώντας το filterχειριστή.

const greaterThanTen = observable.pipe(filter(x => x > 10)); greaterThanTen.subscribe(console.log, console.log, () => console.log("completed")); // OUTPUT // 11 // 12 // 13 // 14 // 15

Το ίδιο μπορεί να αναπαρασταθεί χρησιμοποιώντας το μαρμάρινο διάγραμμα.

Υπάρχουν πολλοί πιο χρήσιμοι χειριστές εκεί έξω. Μπορείτε να δείτε την πλήρη λίστα τελεστών μαζί με παραδείγματα στην επίσημη τεκμηρίωση RxJS εδώ.

Είναι σημαντικό να κατανοήσουμε όλους τους χειριστές που χρησιμοποιούνται συνήθως. Ακολουθούν ορισμένοι χειριστές που χρησιμοποιώ συχνά:

  1. mergeMap
  2. switchMap
  3. exhaustMap
  4. map
  5. catchError
  6. startWith
  7. delay
  8. debounce
  9. throttle
  10. interval
  11. from
  12. of

Redux Παρατηρήσιμα

Σύμφωνα με τον επίσημο ιστότοπο,

Ενδιάμεσο λογισμικό βασισμένο σε RxJS για το Redux. Συνθέστε και ακυρώστε τις ενέργειες ασύγχυσης για να δημιουργήσετε παρενέργειες και άλλα.

Στο Redux, κάθε φορά που αποστέλλεται μια ενέργεια, εκτελείται σε όλες τις λειτουργίες του μειωτήρα και επιστρέφεται μια νέα κατάσταση.

Το Redux-παρατηρούμενο παίρνει όλες αυτές τις αποσταλμένες ενέργειες και τις νέες καταστάσεις και δημιουργεί δύο παρατηρήσιμα από αυτό - Ενέργειες παρατηρήσιμες action$και Παρατηρήσεις κρατών state$.

Οι παρατηρούμενες ενέργειες θα εκπέμπουν όλες τις ενέργειες που αποστέλλονται χρησιμοποιώντας το store.dispatch(). Τα παρατηρήσιμα κράτη θα εκπέμπουν όλα τα νέα αντικείμενα κατάστασης που επιστρέφονται από τον μειωτή ρίζας.

Έπος

Σύμφωνα με τον επίσημο ιστότοπο,

Είναι μια συνάρτηση που λαμβάνει μια ροή ενεργειών και επιστρέφει μια ροή ενεργειών. Ενέργειες, ενέργειες έξω.

Epics are functions that can be used to subscribe to Actions and States Observables. Once subscribed, epics will receive the stream of actions and states as input, and it must return a stream of actions as an output. Actions In - Actions Out.

const someEpic = (action$, state$) => { return action$.pipe( // subscribe to actions observable map(action => { // Receive every action, Actions In return someOtherAction(); // return an action, Actions Out }) ) }

It is important to understand that all the actions received in the Epic have already finished running through the reducers.

Inside an Epic, we can use any RxJS observable patterns, and this is what makes redux-observables useful.

Example: we can use the .filter operator to create a new intermediate observable. Similarly, we can create any number of intermediate observables, but the final output of the final observable must be an action, otherwise an exception will be raised by redux-observable.

const sampleEpic = (action$, state$) => { return action$.pipe( filter(action => action.payload.age >= 18), // can create intermediate observables and streams map(value => above18(value)) // where above18 is an action creator ); }

Every action emitted by the Epics are immediately dispatched using the store.dispatch().

Setup

First, let's install the dependencies.

npm install --save rxjs redux-observable

Create a separate folder named epics to keep all the epics. Create a new file index.js inside the epics folder and combine all the epics using the combineEpics function to create the root epic. Then export the root epic.

import { combineEpics } from 'redux-observable'; import { epic1 } from './epic1'; import { epic2 } from './epic2'; const epic1 = (action$, state$) => { ... } const epic2 = (action$, state$) => { ... } export default combineEpics(epic1, epic2);

Create an epic middleware using the createEpicMiddleware function and pass it to the createStore Redux function.

import { createEpicMiddleware } from 'redux-observable'; import { createStore, applyMiddleware } from 'redux'; import rootEpic from './rootEpics'; const epicMiddleware = createEpicMiddlware(); const store = createStore( rootReducer, applyMiddleware(epicMiddlware) );

Finally, pass the root epic to epic middleware's .run method.

epicMiddleware.run(rootEpic);

Some Practical Usecases

RxJS has a big learning curve, and the redux-observable setup worsens the already painful Redux setup process. All that makes Redux observable look like an overkill. But here are some practical use cases that can change your mind.

Throughout this section, I will be comparing redux-observables with redux-thunk to show how redux-observables can be helpful in complex use-cases. I don't hate redux-thunk, I love it, and I use it every day!

1. Make API Calls

Usecase: Make an API call to fetch comments of a post. Show loaders when the API call is in progress and also handle API errors.

A redux-thunk implementation will look like this,

function getComments(postId){ return (dispatch) => { dispatch(getCommentsInProgress()); axios.get(`/v1/api/posts/${postId}/comments`).then(response => { dispatch(getCommentsSuccess(response.data.comments)); }).catch(() => { dispatch(getCommentsFailed()); }); } }

and this is absolutely correct. But the action creator is bloated.

We can write an Epic to implement the same using redux-observables.

const getCommentsEpic = (action$, state$) => action$.pipe( ofType('GET_COMMENTS'), mergeMap((action) => from(axios.get(`/v1/api/posts/${action.payload.postId}/comments`).pipe( map(response => getCommentsSuccess(response.data.comments)), catchError(() => getCommentsFailed()), startWith(getCommentsInProgress()) ) );

Now it allows us to have a clean and simple action creator like this,

function getComments(postId) { return { type: 'GET_COMMENTS', payload: { postId } } }

2. Request Debouncing

Usecase: Provide autocompletion for a text field by calling an API whenever the value of the text field changes. API call should be made 1 second after the user has stopped typing.

A redux-thunk implementation will look like this,

let timeout; function valueChanged(value) { return dispatch => { dispatch(loadSuggestionsInProgress()); dispatch({ type: 'VALUE_CHANGED', payload: { value } }); // If changed again within 1 second, cancel the timeout timeout && clearTimeout(timeout); // Make API Call after 1 second timeout = setTimeout(() => { axios.get(`/suggestions?q=${value}`) .then(response => dispatch(loadSuggestionsSuccess(response.data.suggestions))) .catch(() => dispatch(loadSuggestionsFailed())) }, 1000, value); } }

It requires a global variable timeout. When we start using global variables, our action creators are not longer pure functions. It also becomes difficult to unit test the action creators that use a global variable.

We can implement the same with redux-observable using the .debounce operator.

const loadSuggestionsEpic = (action$, state$) => action$.pipe( ofType('VALUE_CHANGED'), debounce(1000), mergeMap(action => from(axios.get(`/suggestions?q=${action.payload.value}`)).pipe( map(response => loadSuggestionsSuccess(response.data.suggestions)), catchError(() => loadSuggestionsFailed()) )), startWith(loadSuggestionsInProgress()) );

Now, our action creators can be cleaned up, and more importantly, they can be pure functions again.

function valueChanged(value) { return { type: 'VALUE_CHANGED', payload: { value } } }

3. Request Cancellation

Usecase: Continuing the previous use-case, assume that the user didn't type anything for 1 second, and we made our 1st API call to fetch the suggestions.

Let's say the API itself takes an average of 2-3 seconds to return the result. Now, if the user types something while the 1st API call is in progress, after 1 second, we will make our 2nd API. We can end up having two API calls at the same time, and it can create a race condition.

To avoid this, we need to cancel the 1st API call before making the 2nd API call.

A redux-thunk implementation will look like this,

let timeout; var cancelToken = axios.cancelToken; let apiCall; function valueChanged(value) { return dispatch => { dispatch(loadSuggestionsInProgress()); dispatch({ type: 'VALUE_CHANGED', payload: { value } }); // If changed again within 1 second, cancel the timeout timeout && clearTimeout(timeout); // Make API Call after 1 second timeout = setTimeout(() => { // Cancel the existing API apiCall && apiCall.cancel('Operation cancelled'); // Generate a new token apiCall = cancelToken.source(); axios.get(`/suggestions?q=${value}`, { cancelToken: apiCall.token }) .then(response => dispatch(loadSuggestionsSuccess(response.data.suggestions))) .catch(() => dispatch(loadSuggestionsFailed())) }, 1000, value); } }

Now, it requires another global variable to store the Axios's cancel token. More global variables = more impure functions!

To implement the same using redux-observable, all we need to do is replace .mergeMap with .switchMap.

const loadSuggestionsEpic = (action$, state$) => action$.pipe( ofType('VALUE_CHANGED'), throttle(1000), switchMap(action => from(axios.get(`/suggestions?q=${action.payload.value}`)).pipe( map(response => loadSuggestionsSuccess(response.data.suggestions)), catchError(() => loadSuggestionsFailed()) )), startWith(loadSuggestionsInProgress()) );

Since it doesn't require any changes to our action creators, they can continue to be pure functions.

Ομοίως, υπάρχουν πολλές περιπτώσεις όπου το Redux-Observables λάμπει! Για παράδειγμα, δημοσκόπηση ενός API, εμφάνιση σνακ μπαρ, διαχείριση συνδέσεων WebSocket κ.λπ.

Να συμπεράνω

Εάν αναπτύσσετε μια εφαρμογή Redux που περιλαμβάνει τόσο περίπλοκες περιπτώσεις χρήσης, συνιστάται ιδιαίτερα η χρήση του Redux-Observables. Σε τελική ανάλυση, τα οφέλη από τη χρήση της είναι άμεσα ανάλογα με την πολυπλοκότητα της εφαρμογής σας και είναι προφανές από τις προαναφερόμενες πρακτικές περιπτώσεις χρήσης.

Πιστεύω ακράδαντα ότι η χρήση του σωστού συνόλου βιβλιοθηκών θα μας βοηθήσει να αναπτύξουμε πολύ πιο καθαρές και διατηρήσιμες εφαρμογές, και μακροπρόθεσμα, τα οφέλη από τη χρήση τους θα ξεπεράσουν τα μειονεκτήματα.