Perché usare Redux-Observable su Redux-Saga?


133

Ho usato Redux-Saga . Il codice scritto con esso è facile da ragionare finora, tranne per il fatto che la funzione del generatore JS mi confonde di tanto in tanto la testa. Da quanto ho capito, Redux-Observable può realizzare un lavoro simile che gestisce gli effetti collaterali ma senza usare la funzione del generatore.

Tuttavia, i documenti di Redux-Observable non forniscono molte opinioni sul perché sia ​​superiore a Redux-Saga. Vorrei sapere se non usare la funzione generatore è l'unico vantaggio dell'uso di Redux-Observable. E quali potrebbero essere gli svantaggi, i problemi o i compromessi derivanti dall'uso di Redux-Observable invece di Redux-Saga? Grazie in anticipo.


Avevo fatto un blog divertente ma dettagliato in cui ho trovato Redux-Saga superiore a Redux-Observable per le persone che non vivono / mangiano / respirano osservabili tutto il giorno. Sono sicuro che è fantastico se tutto il tuo stack è osservabile. shift.infinite.red/…
Gant Laborde,

Risposte:


236

Disclaimer: sono uno degli autori di Redux-Observable, quindi è difficile per me essere al 100% imparziale.

Al momento non forniamo alcun motivo per cui l'osservazione redux sia migliore della saga redux perché ... non lo è. 😆

tl; dr ci sono pro e contro per entrambi. Molti ne troveranno uno più intuitivo dell'altro, ma entrambi sono complessi da imparare in modi diversi se non si conoscono RxJS (osservabili con il redux) o generatori / "effetti come dati" (redux-saga).

Risolvono lo stesso problema in modi estremamente simili, ma presentano alcune differenze fondamentali che diventano veramente evidenti solo dopo averle usate abbastanza.

Redux-osservabile difende quasi tutto verso l'idiomatico RxJS. Quindi se hai la conoscenza di RxJS (o la ottieni), l'apprendimento e l'utilizzo di Redux-Observable è super naturale. Ciò significa anche che questa conoscenza è trasferibile a cose diverse dalla redux. Se decidi di passare a MobX, se decidi di passare a Angular2, se decidi di passare a un futuro hotness X, è estremamente probabile che RxJS ti possa aiutare. Questo perché RxJS è una libreria asincrona generica, e per molti versi è come un linguaggio di programmazione in sé - l'intero paradigma di "Programmazione reattiva". RxJS esiste dal 2012 ed è iniziato come una porta di Rx.NET (ci sono "porte" in quasi tutte le principali lingue, è così utile ).

redux-saga fornisce gli stessi operatori basati sul tempo, quindi mentre le conoscenze acquisite sui generatori e sulla gestione degli effetti collaterali in questo stile di gestione dei processi sono trasferibili, gli operatori e l'utilizzo effettivi non vengono utilizzati in nessun'altra libreria principale. Quindi è un po 'sfortunato, ma certamente non dovrebbe essere un affare da solo.

Utilizza anche "effetti come dati" ( qui descritti ), che all'inizio potrebbe essere difficile avvolgere la testa, ma significa che il codice redux-saga in realtà non esegue gli effetti collaterali stessi. Invece, le funzioni di supporto che usi creano oggetti che sono come attività che rappresentano l'intento di fare l'effetto collaterale e quindi la libreria interna lo esegue per te. Questo rende i test estremamente facili, senza la necessità di deridere ed è molto attraente per alcune persone. Tuttavia, ho scoperto personalmente che i test delle tue unità reimplementano gran parte della logica della tua saga, rendendo questi test IMO non molto utili (questa opinione non è condivisa da tutti)

Le persone spesso chiedono perché non facciamo una cosa del genere con l'osservazione redux: per me è fondamentalmente incompatibile con la normale Rx idiomatica. In Rx, utilizziamo operatori come quelli .debounceTime()che incapsulano la logica richiesta per il debounce, ma ciò significa che se volessimo realizzarne una versione che non eseguisse effettivamente il debouncing e invece emettesse oggetti task con l'intento, ora hai perso il potenza di Rx perché non puoi più semplicemente concatenare gli operatori perché opererebbero su quell'oggetto task, non il vero risultato dell'operazione. Questo è davvero difficile da spiegare elegantemente. Richiede ancora una profonda comprensione di Rx per comprendere l'incompatibilità degli approcci. Se vuoi davvero qualcosa del genere, dai un'occhiata ai cicli di reduxche utilizza cycle.js e principalmente ha tali obiettivi. Trovo che richieda troppa cerimonia per i miei gusti, ma ti incoraggio a fare un giro se ti interessa.

Come accennato da ThorbenA, non mi esito ad ammettere che la redux-saga è attualmente (13/10/16) il chiaro leader nella complessa gestione degli effetti collaterali per il redux. È stato avviato in precedenza e ha una community più solida. Quindi c'è molta attrazione nell'usare lo standard di fatto sul nuovo bambino sul blocco. Penso che sia sicuro dire che se usi entrambi senza una conoscenza preliminare, sei in confusione. Entrambi usiamo concetti abbastanza avanzati che una volta "acquisiti", rendono la gestione complessa degli effetti collaterali molto più semplice, ma fino ad allora molti inciampano.

Il consiglio più importante che posso dare è di non portare nessuna di queste librerie prima che tu ne abbia bisogno. Se stai solo effettuando semplici chiamate Ajax, probabilmente non ti servono. redux-thunk è stupido e semplice da imparare e fornisce abbastanza per le basi - ma più è complesso il più difficile (o addirittura impossibile) diventa per redux-thunk. Ma per l'osservazione redux / la saga in molti modi brilla di più tanto più complesso è l'asincrono. C'è anche molto merito nell'usare redux-thunk con uno degli altri (redux-osservable / saga) nello stesso progetto! redux-thunk per le tue cose semplici comuni e poi usando solo redux-osservable / saga per cose complesse. Questo è un ottimo modo per rimanere produttivi, quindi non stai combattendo l'osservazione / la saga del redux per cose che sarebbero banali con il redux-thunk.


3
Ho appena visto i tuoi discorsi (uuhf il suono!) E subito colpito ⌘ + T + "redux-saga vs redux-osservable". Ho usato redux-saga per un po 'di tempo (specialmente in React Native), ma dopo aver visto i tuoi discorsi e questo post posso vedere alcuni casi d'uso (per me) in cui redux-obs. sarebbe effettivamente una misura migliore. Il tuo esempio di debounceTime()aver "perso" il controllo su una logica molto generica mi ha colpito. Grazie per aver spiegato.
Hulvej,

3
Ho appena visto anche il discorso e ho fatto un po 'più di googling in giro. Roba buona @jayphelps, grazie per la condivisione. Mi piace in particolare il tuo commento sull'uso di redux-thunk insieme a redux-osservable / saga. Questo ha molto senso, perché complicare eccessivamente le semplici richieste AJAX quando non è necessario. Detto questo, c'è qualcosa da dire per l'uniformità e il mantenimento della coerenza delle persone. Grazie ancora!
Spets

Prima di passare a redux-saga / redux-osservable, puoi provare redux-dispatch-listener e questo è molto semplice e può già risolvere alcuni dei tuoi casi d'uso: github.com/slorber/redux-dispatch-subscribe
Sebastien Lorber

Questa è stata una risposta molto utile. Grazie! Mi piace il punto di poter trasferire la conoscenza di RxJS ad altri domini / framework.
Anselan,

@jayphelps Quale sarebbe un esempio di "asincrono complesso". Attualmente sto cercando di valutare se dovrei passare da thunk a saga / osservabili per un progetto. Grazie :)
Sam Bokai,

64

Penso che ci siano cose che devi prendere in considerazione.

  1. Complessità
  2. Stile di codifica
  3. Curva di apprendimento
  4. testabilità

Diciamo che vogliamo recuperare l'utente dall'API

// 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'})
        )

Inoltre, ho scritto questo articolo per confrontare a fondo le differenze tra Redux-saga e Redux-Observable. Check-out questo link qui o alla presentazione .


3
questo confronto fianco a fianco del link è fantastico, grazie
rofrol,

1
Adoro il confronto, MA c'è un problema che voglio sollevare. Quando li confronti usando le chiamate API - stai usando fetch per l'osservazione redux. freddo. MA, quando mostri differenze "annullabili" NON usi il recupero - invece usi l'Osservable.ajax interno ... perché? Preferirei tenerlo usando "fetch" o "axios". altrimenti, ottimo lavoro lì.
James Emanon,

5
@jamesemanon Presumo che non stia usando fetch perché l'API fetch non ha ancora l'opzione di annullamento. (altro su questo: github.com/whatwg/fetch/issues/27 )
Daniel Andrei

Caspita, quel confronto approfondito con tutti gli esempi è il migliore. Grazie!
Radek Matěj,

22

Uso Redux-Observable su Redux-Saga perché preferisco lavorare con osservabili rispetto ai generatori. Lo uso con RXJS, che è una potente libreria per lavorare con flussi di dati. Pensalo come un lodash per asincrono. In termini di aspetti negativi, gotcha e compromessi nella scelta l'uno rispetto all'altro, dai un'occhiata a questa risposta di Jay Phelps:

redux-saga come progetto è esistito più a lungo rispetto a redux-osservabile, quindi questo è sicuramente un importante punto di forza. Troverai più documentazione, esempi e probabilmente avrai una community migliore da cui ottenere supporto.

Il contrario è che gli operatori e le API che impari in redux-saga non sono trasferibili quasi quanto l'apprendimento di RxJS, che viene utilizzato ovunque. redux-osservable è super super super semplice internamente, ti sta davvero dando un modo naturale per usare RxJS. Quindi, se conosci RxJS (o vuoi farlo), è una scelta estremamente naturale.

Il mio consiglio al momento per la maggior parte delle persone è che se devi chiedere quale dovresti usare, probabilmente dovresti scegliere redux-saga.


9

Redux-Observable è una libreria straordinaria, la usiamo in produzione per 1,5 anni senza problemi fino ad ora, è perfettamente testabile e può essere facilmente integrata con qualsiasi framework. Stiamo avendo canali di socket paralleli estremamente sovraccarichi e l'unica cosa che ci sta salvando dai blocchi è Redux-Observable

Ho 3 punti che vorrei menzionare qui.

1. Complessità e curva di apprendimento

Redux-saga batte facilmente redux-osservabile qui. Se hai solo bisogno di una semplice richiesta per ottenere l'autorizzazione e non vuoi usare redux-thunk per alcuni motivi, dovresti considerare l'uso di redux-saga, è solo più facile da capire.

Se non hai una conoscenza preliminare di Observable, sarà un dolore per te e il tuo team ti seguirà :)

2. Cosa possono offrirmi Observable e RxJS?

Quando si tratta di logica asincrona Observable è il tuo coltello svizzero, Observable può letteralmente fare quasi tutto per te. Non dovresti mai confrontarli con promesse o generatori è molto più potente, è come confrontare Optimus Prime con Chevrolet.

E che dire di RxJS? È come lodash.js ma per la logica asincrona, una volta dentro non passerai mai a qualcosa di diverso.

3. Estensione reattiva

Controlla questo link

http://reactivex.io/languages.html

L'estensione reattiva è implementata per tutti i moderni linguaggi di programmazione, è solo la chiave della programmazione funzionale.

Quindi trascorri saggiamente il tuo tempo imparando RxJS e usa l'osservazione redux :)


7

Apprezzo la trasferibilità tra le lingue e i tempi di esecuzione di Rx. Anche se la tua app non cambierà lingua, la tua carriera potrebbe. Ottieni la migliore leva possibile sul tuo apprendimento, comunque lo ridimensioni da solo. È un ottimo gateway per .Net LINQ in particolare.


2
Scelta intelligente, anche se i generatori sono anche indipendenti dalla lingua.
Greg Herbowicz,

3

Dato che ci sono un sacco di discorsi osservabili in redux qui, ho pensato di dare il lato saga dell'argomento. Non uso Redux-Observable o RxJS, quindi non posso dare un confronto fianco a fianco, ma ho usato le saghe con grande efficacia.

Per quello che vale, sto usando saghe in produzione in un'applicazione web.

Sagas vs. Thunk

Saga vince a mani basse. Non mi è piaciuto il modo in cui thunk ha messo la logica nei miei creatori di azioni. Ha anche reso problematiche alcune richieste di seguito. Ho guardato brevemente osservabile redux per questo lavoro, ma ho optato per Sagas.

Curva di apprendimento per le saghe

Comprendere cosa sono i generatori e perché sono importanti è la chiave per comprendere le saghe. Ma sottolineerò che non lo fai necessario conoscere i generatori dentro e fuori. Devi solo sapere che stai passando il controllo con l'istruzione yield e che la saga passerà il controllo dopo che il codice asincrono si risolve. Dopo quel po ', non è molto difficile capire cosa sta succedendo in una saga.

I metodi principali della saga sono (nella mia esperienza):

  • call- Chiama qualsiasi bit di codice e ottieni il valore di ritorno. Supporta le promesse. Grande sinergia tra elaborazione asincrona e saghe.
  • select- Chiama un selettore. Questo pezzo è piuttosto brillante. I selettori sono fondamentali per il redux e sono supportati al 100%!
  • put- aka dispatchun'azione. In effetti spedisci quanti ne vuoi!

Ci sono altre funzioni, ma se riesci a padroneggiare quelle tre, sarai in una posizione davvero buona.

Conclusione

Il motivo per cui ho scelto le saghe era la facilità d'uso. redux-osservabile sembrava una sfida. Sono soddisfatto al 100% con le saghe. Più felice di quanto mi aspettassi.

Nella mia esperienza, le saghe sono (molto) migliori dei thunk e relativamente facili da capire. Rx non è la tazza di tè di tutti. Considererei fortemente le saghe invece che osservabili con il redux se non vieni da quell'ecosistema e / o non prevedi di utilizzare Rx in futuro.


2

Se scrivi la tua domanda in Typescript, ti consiglio di controllare senza digitare . È ispirato a Redux-Observable e dipende anche da RxJS, ma esiste l'intero ecosistema per la creazione dell'app.

I maggiori svantaggi di redux-osservabili / redux-saga sono la mancanza di linee guida. Non ci sono linee guida ufficiali su come ridurre i carichi, saghe o epiche pigri. La suddivisione del codice è fondamentale quando si ridimensionano le app più grandi. Le soluzioni personalizzate per il caricamento lento di solito non funzionano con HMR causando una scarsa esperienza degli sviluppatori.

Professionisti senza nome:

  1. Progettato per TypeScript
    Tutte le API sono progettate per dattiloscritto e sicurezza dei tipi:
    • Typescript aumenterà la tua produttività, non ti rallenta.
    • Sono necessarie solo le annotazioni necessarie: stato, argomenti dell'azione.
    • Nessun typecasting. Tutto viene dedotto automaticamente. Il 95% del codice sembra javascript puro.
    • No RootAction, RootEpic, RootState o altri tipi di helper.
  2. Fornire tutti i blocchi
    • Typeless include tutto per creare app di medie dimensioni o di livello aziendale.
    • Non è necessario fare affidamento su più piccole librerie.
  3. modularità
    • La corretta modularità è fondamentale per la creazione di app scalabili.
    • Non è necessario creare file root per epiche, riduttori, tipi, ecc. Una volta creato un nuovo modulo, è possibile collegarlo da qualsiasi luogo. Simile ai componenti standard di React.
  4. Supponente
    • Tutti i casi d'uso comuni e i problemi sono risolti per impostazione predefinita. Non c'è bisogno di pensare troppo a come risolvere problemi banali.
    • Vengono forniti tutti i consigli e le migliori pratiche!

Dai un'occhiata a https://typeless.js.org/


1
Dovresti aggiungere una dichiarazione di non responsabilità quando consigli il software per il quale sei il principale collaboratore.
Hagelt18,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.