Jika toko mempertahankan statusnya sendiri dan memiliki kemampuan untuk memanggil layanan jaringan dan penyimpanan data dalam melakukannya ... dalam hal ini tindakannya hanyalah pelintas pesan bodoh,
-ATAU-
... haruskah penyimpanan menjadi penerima bodoh dari data yang tidak dapat diubah dari tindakan (dan tindakan adalah tindakan yang mengambil / mengirim data antara sumber eksternal? Simpan dalam contoh ini akan bertindak sebagai model tampilan dan akan dapat menggabungkan / memfilter mereka data sebelum menetapkan basis negara mereka sendiri pada data yang tidak dapat diubah yang diberi makan oleh tindakan.
Menurut saya, itu harus salah satu atau yang lain (bukan campuran keduanya). Jika ya, mengapa yang satu lebih disukai / direkomendasikan daripada yang lain?
sumber
Jawaban:
Saya telah melihat pola fluks diterapkan dengan dua cara, dan setelah melakukan keduanya sendiri (awalnya menggunakan pendekatan sebelumnya), saya percaya bahwa penyimpanan harus menjadi penerima data yang bodoh dari tindakan, dan bahwa pemrosesan penulisan yang tidak sinkron harus dilakukan di pencipta aksi. ( Pembacaan Async dapat ditangani secara berbeda .) Menurut pengalaman saya, ini memiliki beberapa manfaat, dalam urutan kepentingannya:
Toko Anda menjadi sangat sinkron. Hal ini membuat logika penyimpanan Anda lebih mudah diikuti dan sangat mudah untuk diuji — cukup buat instance penyimpanan dengan beberapa status tertentu, kirimkan tindakan, dan periksa untuk melihat apakah status berubah seperti yang diharapkan. Lebih lanjut, salah satu konsep inti dalam fluks adalah untuk mencegah pengiriman bertingkat dan untuk mencegah beberapa pengiriman sekaligus; ini sangat sulit dilakukan ketika toko Anda melakukan pemrosesan asinkron.
Semua pengiriman tindakan terjadi dari pembuat tindakan. Jika Anda menangani operasi asinkron di toko Anda dan ingin menjaga penangan tindakan toko Anda tetap sinkron (dan Anda harus untuk mendapatkan jaminan pengiriman tunggal flux), toko Anda perlu mengaktifkan tindakan SUKSES dan GAGAL tambahan sebagai respons terhadap asinkron pengolahan. Menempatkan kiriman ini dalam pembuat tindakan malah membantu memisahkan pekerjaan pembuat tindakan dan toko; Selain itu, Anda tidak perlu menggali logika toko Anda untuk mencari tahu dari mana tindakan akan dikirim. Tindakan asinkron yang khas dalam kasus ini mungkin terlihat seperti ini (ubah sintaksis
dispatch
panggilan berdasarkan rasa fluks yang Anda gunakan):Logika yang dapat diduplikasi di berbagai tindakan harus diekstraksi menjadi modul terpisah; dalam contoh ini, modul itu adalah
SomeDataAccessLayer
, yang menangani permintaan Ajax yang sebenarnya.Anda membutuhkan lebih sedikit pembuat tindakan. Ini bukan masalah besar, tapi menyenangkan untuk dimiliki. Seperti disebutkan di # 2, jika toko Anda memiliki penanganan pengiriman tindakan sinkron (dan seharusnya), Anda harus mengaktifkan tindakan ekstra untuk menangani hasil operasi asinkron. Melakukan pengiriman di pembuat tindakan berarti bahwa pembuat tindakan tunggal dapat mengirimkan ketiga jenis tindakan dengan menangani hasil akses data asinkron itu sendiri.
sumber
"SOME_ACTION"
), menggunakan API untuk membuat permintaan (SomeDataAccessLayer.doSomething(userId)
) yang mengembalikan sebuah janji, dan dalam dua.then
fungsi, mengirimkan tindakan tambahan. Status permintaan dapat (lebih atau kurang) memetakan ke menyimpan status jika aplikasi perlu mengetahui tentang status negara. Bagaimana peta ini tergantung pada aplikasi (misalnya, mungkin setiap komentar memiliki status kesalahan tersendiri, ala Facebook, atau mungkin ada satu komponen kesalahan global)Saya tweet pertanyaan ini ke devs di Facebook dan jawaban yang saya dapatkan dari Bill Fisher adalah:
sumber
a call from store works better when action triggers from non-human driver
?Toko harus melakukan segalanya, termasuk mengambil data, dan memberi sinyal ke komponen bahwa data toko telah diperbarui. Mengapa? Karena tindakan kemudian bisa ringan, sekali pakai, dan dapat diganti tanpa memengaruhi perilaku penting. Semua perilaku dan fungsi penting terjadi di toko. Ini juga mencegah duplikasi perilaku yang seharusnya disalin dalam dua tindakan yang sangat mirip tetapi berbeda. Toko-toko adalah satu - satunya sumber (menangani) kebenaran.
Dalam setiap implementasi Flux, saya telah melihat Actions pada dasarnya adalah event string yang diubah menjadi objek, seperti biasanya Anda akan memiliki event bernama "anchor: clicked" tetapi di Flux akan didefinisikan sebagai AnchorActions.Clicked. Mereka bahkan sangat "bodoh" sehingga sebagian besar implementasi memiliki objek Dispatcher terpisah untuk benar-benar mengirimkan peristiwa ke toko yang mendengarkan.
Secara pribadi saya suka implementasi Flux Reflux di mana tidak ada objek Dispatcher yang terpisah dan objek Action melakukan pengiriman sendiri.
sunting: Flux Facebook benar-benar menarik "pembuat tindakan" sehingga mereka menggunakan tindakan cerdas. Mereka juga menyiapkan muatan menggunakan toko:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (baris 27 dan 28)
Callback saat selesai kemudian akan memicu tindakan baru kali ini dengan data yang diambil sebagai payload:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
Jadi saya rasa itulah solusi yang lebih baik.
sumber
Saya akan memberikan argumen yang mendukung Tindakan "bodoh".
Dengan menempatkan tanggung jawab untuk mengumpulkan data tampilan di Tindakan Anda, Anda menghubungkan Tindakan Anda dengan persyaratan data tampilan Anda.
Sebaliknya, Actions generik, yang secara deklaratif mendeskripsikan maksud pengguna, atau beberapa transisi status dalam aplikasi Anda, memungkinkan Store apa pun yang merespons Action tersebut untuk mengubah maksud, menjadi status yang disesuaikan secara khusus untuk tampilan yang dilanggani.
Ini cocok untuk lebih banyak, tetapi lebih kecil, Toko yang lebih khusus. Saya memperdebatkan gaya ini karena
Tujuan Store adalah untuk menyediakan data ke tampilan. Nama "Tindakan" menunjukkan kepada saya bahwa tujuannya adalah untuk menjelaskan perubahan dalam Aplikasi saya.
Misalkan Anda harus menambahkan widget ke tampilan Dasbor yang ada, yang menunjukkan beberapa data agregat baru yang mewah yang baru saja diluncurkan oleh tim backend Anda.
Dengan Tindakan "cerdas", Anda mungkin perlu mengubah Tindakan "segarkan dasbor" Anda, untuk menggunakan API baru. Namun, "Menyegarkan dasbor" dalam arti abstrak tidak berubah. Persyaratan data dari pandangan Anda adalah apa yang telah berubah.
Dengan Tindakan "dumb", Anda dapat menambahkan Store baru untuk digunakan widget baru, dan mengaturnya sehingga ketika menerima jenis Tindakan "refresh-dashboard", ia mengirim permintaan untuk data baru, dan memaparkannya ke widget baru setelah siap. Masuk akal bagi saya bahwa saat lapisan tampilan membutuhkan lebih banyak atau berbagai data, hal-hal yang saya ubah adalah sumber datanya: Toko.
sumber
flux-react-router-demo gaeron memiliki variasi utilitas yang bagus dari pendekatan 'benar'.
ActionCreator membuat janji dari layanan API eksternal, lalu meneruskan janji dan tiga konstanta tindakan ke
dispatchAsync
fungsi di proxy / Dispatcher yang diperluas.dispatchAsync
akan selalu mengirimkan tindakan pertama misalnya 'GET_EXTERNAL_DATA' dan setelah janji muncul, tindakan itu akan mengirimkan 'GET_EXTERNAL_DATA_SUCCESS' atau 'GET_EXTERNAL_DATA_ERROR'.sumber
Jika Anda ingin suatu hari memiliki lingkungan pengembangan yang sebanding dengan apa yang Anda lihat dalam video terkenal Bret Victor, Inventing on Principle , Anda sebaiknya menggunakan toko bodoh yang hanya merupakan proyeksi tindakan / peristiwa di dalam struktur data, tanpa efek samping. Ini juga akan membantu jika toko Anda sebenarnya adalah anggota dari struktur data global yang tidak berubah, seperti di Redux .
Penjelasan lebih lanjut di sini: https://stackoverflow.com/a/31388262/82609
sumber