Mengapa menggunakan Redux-Observable di atas Redux-Saga?

133

Saya telah menggunakan Redux-Saga . Kode yang ditulis dengan mudah untuk alasan sejauh ini, kecuali fungsi generator JS mengacaukan kepala saya dari waktu ke waktu. Dari pemahaman saya, Redux-Observable dapat mencapai pekerjaan serupa yang menangani efek samping tetapi tanpa menggunakan fungsi generator.

Namun, dokumen dari Redux-Observable tidak memberikan banyak pendapat tentang mengapa itu lebih unggul dari Redux-Saga. Saya ingin tahu apakah tidak menggunakan fungsi generator adalah satu-satunya manfaat menggunakan Redux-Observable. Dan apa yang bisa menjadi kerugian, gotcha atau kompromi dari menggunakan Redux-Observable, bukan Redux-Saga? Terima kasih sebelumnya.

Ivan Wang
sumber
Saya telah membuat blog yang menyenangkan tapi terperinci di mana saya menemukan Redux-Saga lebih unggul dari Redux-Observable untuk orang-orang yang tidak hidup / makan / bernafas yang bisa diamati sepanjang hari. Saya yakin itu bagus jika seluruh tumpukan Anda dapat diamati. shift.infinite.red/…
Gant Laborde

Jawaban:

236

Penafian: Saya adalah salah satu penulis redux-observable sehingga sulit bagi saya untuk 100% tidak memihak.

Kami saat ini tidak memberikan alasan redux-observable lebih baik daripada redux-saga karena ... tidak. 😆

tl; dr ada pro dan kontra untuk keduanya. Banyak yang akan menemukan satu lebih intuitif daripada yang lain, tetapi keduanya kompleks untuk dipelajari dengan cara yang berbeda jika Anda tidak tahu RxJS (redux-observable) atau generator / "efek sebagai data" (redux-saga).

Mereka memecahkan masalah yang sama dengan cara yang sangat mirip, tetapi memiliki beberapa perbedaan mendasar yang hanya menjadi nyata setelah Anda menggunakannya dengan cukup.

redux-observable hampir mengubah segalanya menjadi RxJS idiomatik. Jadi jika Anda memiliki pengetahuan RxJS (atau memperolehnya), belajar dan menggunakan redux-observable adalah super alami. Itu juga berarti bahwa pengetahuan ini dapat ditransfer ke hal lain selain redux. Jika Anda memutuskan untuk beralih ke MobX, jika Anda memutuskan untuk beralih ke Angular2, jika Anda memutuskan untuk beralih ke beberapa hotness X di masa mendatang, kemungkinan sangat bagus bahwa RxJS dapat membantu Anda. Ini karena RxJS adalah pustaka async umum, dan dalam banyak hal seperti bahasa pemrograman itu sendiri — seluruh paradigma "Pemrograman Reaktif". RxJS ada sejak 2012 dan dimulai sebagai port Rx.NET (ada "port" di hampir setiap bahasa utama, itu berguna ).

redux-saga menyediakan operator berbasis waktu itu sendiri, jadi sementara pengetahuan yang Anda peroleh tentang generator dan penanganan efek samping dalam gaya proses-manajer ini dapat ditransfer, operator dan penggunaan yang sebenarnya tidak digunakan di perpustakaan utama lainnya. Jadi itu sedikit disayangkan, tetapi tentu saja tidak seharusnya menjadi pemecah kesepakatan dengan sendirinya.

Itu juga menggunakan "efek sebagai data" ( dijelaskan di sini ), yang mungkin sulit untuk membungkus kepala Anda pada awalnya, tetapi itu berarti bahwa kode redux-saga Anda tidak benar-benar melakukan efek samping itu sendiri. Sebagai gantinya, fungsi helper yang Anda gunakan membuat objek yang seperti tugas yang mewakili maksud untuk melakukan efek samping dan kemudian pustaka internal melakukan itu untuk Anda. Ini membuat pengujian sangat mudah, tanpa perlu mengejek dan sangat menarik bagi sebagian orang. Namun, saya pribadi telah menemukan bahwa ini berarti unit test Anda menerapkan kembali banyak logika saga Anda - membuat tes tersebut tidak terlalu berguna untuk IMO (pendapat ini tidak dibagikan oleh semua orang)

Orang sering bertanya mengapa kita tidak melakukan sesuatu seperti itu dengan redux-observable: bagi saya itu pada dasarnya tidak sesuai dengan Rx idiomatik normal. Dalam Rx, kami menggunakan operator seperti .debounceTime()itu merangkum logika yang diperlukan untuk mendebounce, tetapi itu berarti jika kami ingin membuat versi itu yang tidak benar-benar melakukan debouncing dan sebagai gantinya memancarkan objek tugas dengan maksud, Anda sekarang telah kehilangan kekuatan Rx karena Anda tidak bisa hanya rantai operator lagi karena mereka akan beroperasi pada objek tugas itu, bukan hasil nyata dari operasi. Ini sangat sulit dijelaskan dengan elegan. Lagi-lagi membutuhkan pemahaman Rx untuk memahami ketidakcocokan pendekatan. Jika Anda benar - benar menginginkan sesuatu seperti itu, lihat siklus reduxyang menggunakan cycle.js dan sebagian besar memiliki tujuan tersebut. Saya menemukan itu membutuhkan upacara terlalu banyak untuk seleraku, tetapi saya mendorong Anda untuk mencobanya jika itu menarik minat Anda.

Seperti yang disebutkan ThorbenA, saya tidak menghindar untuk mengakui bahwa redux-saga saat ini (13/10/16) adalah pemimpin yang jelas dalam manajemen efek samping kompleks untuk redux. Itu dimulai lebih awal dan memiliki komunitas yang lebih kuat. Jadi ada banyak daya tarik untuk menggunakan standar de facto atas anak baru di blok. Saya pikir aman untuk mengatakan jika Anda menggunakan baik tanpa sepengetahuan sebelumnya, Anda berada dalam kebingungan. Kami berdua menggunakan konsep yang cukup canggih yang sekali Anda "dapatkan", membuat manajemen efek samping yang kompleks jauh lebih mudah, tetapi sampai saat itu banyak yang tersandung.

Saran paling penting yang bisa saya berikan adalah tidak membawa salah satu perpustakaan ini sebelum Anda membutuhkannya. Jika Anda hanya membuat panggilan ajax sederhana, Anda mungkin tidak membutuhkannya. redux-thunk adalah bodoh sederhana untuk dipelajari dan menyediakan cukup untuk dasar-dasar - tetapi semakin kompleks async semakin sulit (atau bahkan tidak mungkin) menjadi redux-thunk. Tetapi untuk redux-observable / saga dalam banyak hal ia bersinar paling kompleks dari async. Ada juga banyak manfaat dalam menggunakan redux-thunk dengan yang lain (redux-observable / saga) dalam proyek yang sama! redux-thunk untuk hal-hal sederhana umum Anda dan kemudian hanya menggunakan redux-observable / saga untuk hal-hal kompleks. Itu cara yang bagus untuk tetap produktif, jadi Anda tidak berjuang redux-observable / saga untuk hal-hal yang sepele dengan redux-thunk.

jayphelps
sumber
3
Baru saja melihat pembicaraan Anda (uuhf suaranya!), Dan segera tekan ⌘ + T + "redux-saga vs redux-observable". Saya telah menggunakan redux-saga untuk beberapa waktu sekarang (terutama di React Native), tetapi setelah menonton ceramah Anda dan postingan ini saya dapat melihat beberapa case-use (untuk saya) di mana redux-obs. sebenarnya akan lebih cocok. Contoh Anda tentang debounceTime()dan telah "kehilangan" kendali atas jenis logika yang sangat umum membuat saya terpukul. Terima kasih telah menjelaskan.
Hulvej
3
Baru saja melihat pembicaraan dan melakukan sedikit lebih banyak googling. Bagus @jayphelps, terima kasih sudah berbagi. Saya terutama menyukai komentar Anda menggunakan redux-thunk bersama dengan redux-observable / saga. Itu masuk akal, mengapa terlalu rumit permintaan AJAX sederhana ketika itu tidak perlu. Yang mengatakan, ada sesuatu yang bisa dikatakan untuk keseragaman dan membuat orang konsisten. Terima kasih lagi!
Spesialis
Sebelum meningkatkan ke redux-saga / redux-observable, Anda dapat mencoba redux-dispatch-listener dan yang sangat sederhana dan sudah dapat menyelesaikan beberapa penggunaan Anda: github.com/slorber/redux-dispatch-subscribe
Sebastien Lorber
Ini adalah jawaban yang sangat berguna. Terima kasih! Saya suka poin tentang bisa mentransfer pengetahuan tentang RxJS ke domain / kerangka kerja lain.
Anselan
@ jayphelps Apa yang akan menjadi contoh "async kompleks". Saat ini mencoba untuk menilai apakah saya harus beralih dari thunk ke saga / diamati untuk suatu proyek. Terima kasih :)
Sam Bokai
64

Saya pikir ada beberapa hal yang perlu Anda pertimbangkan.

  1. Kompleksitas
  2. Gaya Pengodean
  3. Kurva Belajar
  4. Testabilitas

Katakanlah kita ingin mengambil pengguna dari 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'})
        )

Juga, saya telah menulis artikel ini untuk membandingkan perbedaan antara Redux-saga dan Redux-Observable secara mendalam. Lihat tautan ini di sini atau presentasi .

Wayne Chiu
sumber
3
perbandingan berdampingan dari tautan ini sangat bagus, terima kasih
rofrol
1
Saya suka perbandingannya, TETAPI ada masalah dengannya saya ingin membahasnya. Ketika Anda membandingkannya menggunakan panggilan api - Anda menggunakan pengambilan untuk diamati-redux. keren. TETAPI, ketika Anda menunjukkan perbedaan "dapat dibatalkan" .. Anda TIDAK menggunakan fetch - alih-alih Anda menggunakan internal Observable.ajax ... mengapa? Saya lebih suka menyimpannya menggunakan "fetch" atau "axios". kalau tidak, kerja bagus di sana.
james emanon
5
@jamesemanon Saya menganggap dia tidak menggunakan fetch karena fetch API belum memiliki opsi untuk membatalkan. (lebih lanjut tentang ini: github.com/whatwg/fetch/issues/27 )
Daniel Andrei
Wow, perbandingan mendalam dengan semua contoh adalah yang terbaik. Terima kasih!
Radek Matěj
22

Saya menggunakan Redux-Observable daripada Redux-Saga karena lebih suka bekerja dengan observable daripada generator. Saya menggunakannya dengan RXJS, yang merupakan perpustakaan yang kuat untuk bekerja dengan aliran data. Anggap saja seperti asas untuk async. Dalam hal kerugian, gotcha dan kompromi dalam memilih satu dari yang lain, lihat jawaban ini dari Jay Phelps:

redux-saga sebagai proyek telah ada lebih lama dari redux-observable jadi itu jelas merupakan salah satu nilai jual utama. Anda akan menemukan lebih banyak dokumentasi, contoh, dan kemungkinan memiliki komunitas yang lebih baik untuk mendapatkan dukungan.

Penghitungnya adalah bahwa operator dan API yang Anda pelajari di redux-saga hampir tidak dapat dipindahtangankan seperti mempelajari RxJS, yang digunakan di semua tempat. redux-observable super internal super super sederhana, itu benar-benar hanya memberi Anda cara alami bagi Anda untuk menggunakan RxJS. Jadi jika Anda tahu RxJS (atau ingin), itu sangat alami.

Saran saya saat ini bagi kebanyakan orang adalah jika Anda harus bertanya yang mana yang harus Anda gunakan, Anda mungkin harus memilih redux-saga.

ThorbenA
sumber
9

Redux-Observable adalah perpustakaan yang luar biasa, kami menggunakannya dalam produksi selama 1,5 tahun tanpa masalah sejauh ini, sangat dapat diuji dan dapat dengan mudah diintegrasikan dengan kerangka kerja apa pun. Kami mengalami saluran soket paralel yang sangat kelebihan beban dan satu-satunya hal yang menyelamatkan kami dari pembekuan adalah Redux-Observable

Saya punya 3 poin yang ingin saya sebutkan di sini.

1. Kompleksitas dan kurva belajar

Redux-saga mudah mengalahkan redux yang dapat diamati di sini. Jika Anda hanya membutuhkan permintaan sederhana untuk menyelesaikan otorisasi dan Anda tidak ingin menggunakan redux-thunk untuk beberapa alasan, Anda harus mempertimbangkan untuk menggunakan redux-saga, itu hanya lebih mudah untuk dipahami.

Jika Anda tidak memiliki pengetahuan sebelumnya tentang Observable, itu akan merepotkan Anda dan tim Anda tentu saja :)

2. Apa yang bisa diamati dan RxJS tawarkan kepada saya?

Dalam hal logika async, Observable adalah pisau Swiss Anda, Observable secara harfiah dapat melakukan hampir semua hal untuk Anda. Anda tidak boleh membandingkannya dengan janji atau generator yang jauh lebih kuat, sama seperti membandingkan Optimus Prime dengan Chevrolet.

Dan bagaimana dengan RxJS? Ini seperti lodash.js tetapi untuk logika async, sekali Anda masuk Anda tidak akan pernah beralih ke sesuatu yang berbeda.

3. Ekstensi reaktif

Periksa tautan ini

http://reactivex.io/languages.html

Ekstensi reaktif diterapkan untuk semua bahasa pemrograman modern, itu hanya kunci Anda untuk pemrograman fungsional.

Jadi habiskan waktu Anda dengan bijak mempelajari RxJS dan gunakan redux-observable :)

Denis Rybalka
sumber
7

Saya menghargai transferabilitas lintas bahasa dan runtime yang dimiliki Rx. Bahkan jika aplikasi Anda tidak akan mengubah bahasa, karier Anda mungkin. Dapatkan pengaruh terbaik yang Anda dapat pada pembelajaran Anda, namun Anda mengukurnya sendiri. Ini adalah gateway yang bagus untuk .Net LINQ pada khususnya.

Dean Radcliffe
sumber
2
Pilihan cerdas, meskipun generator juga agnostik bahasa.
Greg Herbowicz
3

Karena ada banyak pembicaraan redux-diamati di sini, saya pikir saya akan memberikan sisi saga argumen. Saya tidak menggunakan redux-observable atau RxJS, jadi saya tidak bisa memberikan perbandingan berdampingan, tetapi saya telah menggunakan saga untuk efek yang besar.

Untuk apa nilainya, saya menggunakan kisah-kisah dalam produksi dalam aplikasi web.

Sagas vs Thunk

Saga menang telak. Saya tidak suka bagaimana thunk menempatkan logika pada pembuat tindakan saya. Itu juga membuat melakukan beberapa permintaan berturut-turut merepotkan. Saya melihat redux-diamati untuk pekerjaan ini, tetapi memutuskan untuk Sagas.

Kurva Belajar untuk Sagas

Memahami apa itu generator dan mengapa mereka penting adalah kunci untuk memahami kisah-kisah. Tapi saya akan menekankan bahwa Anda tidak perlu tahu generator luar dan dalam. Anda hanya perlu tahu bahwa Anda melepaskan kendali dengan pernyataan hasil, dan bahwa saga akan mengembalikan kontrol setelah kode async Anda terselesaikan. Setelah itu, tidak terlalu sulit untuk memahami apa yang terjadi dalam hikayat.

Metode inti saga adalah (menurut pengalaman saya):

  • call- Panggil sedikit kode dan dapatkan nilai kembali. Mendukung janji. Sinergi yang hebat antara pemrosesan async dan kisah-kisah.
  • select- Panggil pemilih. Bit ini agak brilian. Selektor adalah inti dari redux, dan mereka 100% didukung!
  • put- alias dispatchtindakan. Bahkan mengirimkan sebanyak yang Anda inginkan!

Ada fungsi lain, tetapi jika Anda bisa menguasai ketiganya, Anda akan berada di tempat yang sangat bagus.

Kesimpulan

Alasan saya memilih saga adalah kemudahan penggunaan. redux-observable tampak seperti sebuah tantangan. Saya 100% puas dengan kisah-kisah. Lebih bahagia dari yang pernah saya duga.

Dalam pengalaman saya, Sagas (cara) lebih baik dari thunks dan relatif mudah dimengerti. Rx bukan cangkir teh semua orang. Saya akan sangat mempertimbangkan saga alih-alih diamati-ulang jika Anda tidak berasal dari ekosistem itu dan / atau tidak berencana menggunakan Rx di masa depan.

Julius Ecker
sumber
2

Jika Anda menulis aplikasi Anda dalam naskah, saya sarankan memeriksa tanpa huruf . Ini terinspirasi oleh Redux-Observable, dan juga tergantung pada RxJS, tetapi ada seluruh ekosistem untuk membangun aplikasi.

Kontra terbesar dari redux-observable / redux-saga adalah kurangnya panduan. Tidak ada pedoman resmi tentang cara malas memuat reduksi, kisah atau epos. Pemecahan kode sangat penting saat menskala aplikasi yang lebih besar. Solusi khusus untuk pemuatan yang malas biasanya tidak bekerja dengan HMR yang menyebabkan pengalaman pengembang yang buruk.

Pro biasa:

  1. Dirancang untuk TypeScript
    Semua API dirancang untuk naskah dan keamanan tipe:
    • Skrip akan meningkatkan produktivitas Anda, bukan memperlambat Anda.
    • Hanya anotasi yang diperlukan yang diperlukan: status, argumen tindakan.
    • Tidak ada typecasting. Semuanya disimpulkan secara otomatis. 95% kode terlihat seperti javascript murni.
    • Tidak ada RootAction, RootEpic, RootState atau jenis pembantu lainnya.
  2. Berikan semua blok bangunan
    • Typeless menyertakan semuanya untuk membangun aplikasi tingkat menengah atau perusahaan.
    • Anda tidak perlu bergantung pada banyak perpustakaan kecil.
  3. Modularitas
    • Modularitas yang tepat sangat penting untuk membangun aplikasi yang skalabel.
    • Tidak perlu membuat file root untuk epos, reduksi, tipe, dll. Setelah Anda membuat modul baru, Anda dapat melampirkannya dari mana saja. Mirip dengan komponen Bereaksi standar.
  4. Dogmatis
    • Semua kasus dan masalah penggunaan umum diselesaikan secara default. Tidak perlu terlalu memikirkan bagaimana cara memperbaiki masalah sepele.
    • Semua rekomendasi dan praktik terbaik disediakan!

Lihat https://typeless.js.org/

langit
sumber
1
Anda harus menambahkan pelepasan tanggung jawab hukum saat merekomendasikan perangkat lunak tempat Anda menjadi kontributor utama.
Hagelt18