Rumah >hujung hadapan web >tutorial js >Pengenalan kepada pengaturcaraan reaktif berfungsi dengan RXJS
Artikel ini dikaji semula oleh Moritz Kröger, Bruno Mota dan Vildan Softic. Terima kasih kepada semua pengulas rakan sebaya SitePoint untuk membuat kandungan SitePoint yang terbaik boleh!
Sebelum kita menyelam ke dalam topik kita perlu menjawab soalan penting: Apakah pengaturcaraan reaktif? Sehingga hari ini, jawapan yang paling popular ialah pengaturcaraan reaktif adalah pengaturcaraan dengan aliran data serentak. Kebanyakan masa kita akan mendapati perkataan serentak digantikan oleh asynchronous, bagaimanapun, kita akan melihat kemudian bahawa aliran itu tidak perlu tidak segerak.Adalah mudah untuk melihat bahawa pendekatan "Segala -galanya adalah aliran" boleh digunakan secara langsung kepada masalah pengaturcaraan kami. Lagipun, CPU tidak lebih daripada peranti yang memproses aliran maklumat yang terdiri daripada arahan dan data. Matlamat kami adalah untuk memerhatikan aliran itu dan mengubahnya dalam kes data tertentu.
Prinsip pengaturcaraan reaktif tidak sepenuhnya baru kepada JavaScript. Kami sudah mempunyai perkara seperti mengikat harta, corak EventeMitter, atau aliran Node.js. Kadang -kadang keanggunan kaedah ini datang dengan penurunan prestasi, abstraksi yang terlalu rumit, atau masalah dengan debugging. Biasanya, kelemahan ini adalah minimum berbanding dengan kelebihan lapisan abstraksi baru. Contoh -contoh minimum kami, tentu saja, tidak mencerminkan aplikasi biasa, tetapi menjadi pendek dan ringkas yang mungkin.
Tanpa berlengah lagi, mari kita dapatkan tangan kita kotor dengan bermain dengan perpustakaan reaktif untuk perpustakaan JavaScript (RXJS). RXJS menggunakan banyak chaining, yang merupakan teknik popular yang juga digunakan di perpustakaan lain seperti jQuery. Panduan untuk kaedah chaining (dalam konteks Ruby) boleh didapati di Sitepoint.
Secara umum, kita boleh membezakan dua jenis aliran: dalaman dan luaran. Walaupun bekas itu boleh dianggap buatan dan dalam kawalan kami, yang terakhir datang dari sumber -sumber di luar kawalan kami. Aliran luaran boleh dicetuskan (secara langsung atau tidak langsung) dari kod kami.
Biasanya, aliran tidak menunggu kami. Mereka berlaku sama ada kita boleh mengendalikannya atau tidak. Contohnya jika kita mahu memerhatikan kereta di jalan raya, kita tidak akan dapat memulakan semula aliran kereta. Aliran itu berlaku bebas jika kita memerhatikannya atau tidak. Dalam terminologi Rx kita panggil ini
Hot Observable . Rx juga memperkenalkan Observables Cold , yang berkelakuan lebih seperti Iterator Standard, supaya maklumat dari aliran terdiri daripada semua item untuk setiap pemerhati.
Imej berikut menggambarkan beberapa jenis aliran luaran. Kami melihat bahawa permintaan (dahulu bermula) dan secara amnya menubuhkan cangkuk web disebutkan, serta peristiwa UI seperti interaksi tetikus atau keyboard. Akhirnya, kami juga boleh menerima data dari peranti, contohnya sensor GPS, pecutan, atau sensor lain.
Imej juga mengandungi satu aliran yang dinyatakan sebagai
. Mesej boleh muncul dalam beberapa bentuk. Salah satu bentuk yang paling mudah ialah komunikasi antara laman web kami dan beberapa laman web lain. Contoh lain termasuk komunikasi dengan websocket atau pekerja web. Mari lihat beberapa contoh kod untuk yang terakhir. Kod pekerja dibentangkan di bawah. Kod ini cuba mencari nombor perdana dari 2 hingga 10
10. Sebaik sahaja nombor dijumpai hasilnya dilaporkan.
Secara klasik, pekerja web (dianggap berada dalam fail prime.js) dimasukkan seperti berikut. Untuk keringkasan kami melangkau cek untuk sokongan pekerja web dan kesahihan hasil yang dikembalikan.<span>(function (start<span>, end</span>) { </span> <span>var n = start - 1; </span> <span>while (n++ < end) { </span> <span>var k = Math.sqrt(n); </span> <span>var found = false; </span> <span>for (var i = 2; !found && i <= k; ++i) { </span> found <span>= n % i === 0; </span> <span>} </span> <span>if (!found) { </span> <span>postMessage(n.toString()); </span> <span>} </span> <span>} </span><span>})(2, 1e10); </span>
lebih banyak maklumat mengenai pekerja web dan pelbagai threading dengan JavaScript boleh didapati dalam artikel JavaScript selari dengan paralel.js.
<span>var worker = new Worker('prime.js'); </span>worker<span>.addEventListener('message', function (ev) { </span> <span>var primeNumber = ev.data * 1; </span> <span>console.log(primeNumber); </span><span>}, false); </span>
Memandangkan contoh di atas, kita tahu bahawa nombor perdana mengikuti pengedaran asimtotik di kalangan bilangan bulat positif. Untuk x hingga ∞ kita memperoleh pengedaran x / log (x). Ini bermakna kita akan melihat lebih banyak nombor pada mulanya. Di sini, cek juga lebih murah (iaitu, kami menerima lebih banyak nombor perdana per unit masa pada mulanya daripada kemudian.)
Ini boleh digambarkan dengan paksi masa yang mudah dan gumpalan untuk keputusan:
Dalam kedua -dua senario jawapannya adalah untuk mengagregatkan peristiwa sebelumnya dalam selang waktu tertentu. Perbezaan antara kedua -dua senario yang diterangkan adalah bahawa nombor utama harus selalu ditunjukkan selepas selang waktu yang diberikan (iaitu, beberapa nombor perdana hanya berpotensi tertunda dalam persembahan). Sebaliknya, pertanyaan carian hanya akan mencetuskan permintaan baru jika tiada strok utama berlaku semasa selang yang ditentukan. Oleh itu, pemasa ditetapkan semula apabila strok utama telah dikesan.
rxjs untuk menyelamat
Blok bangunan asas RXJs adalah pemerhatian (pengeluar) dan pemerhati (pengguna). Kami sudah menyebut kedua -dua jenis pemerhatian:
<span>(function (start<span>, end</span>) { </span> <span>var n = start - 1; </span> <span>while (n++ < end) { </span> <span>var k = Math.sqrt(n); </span> <span>var found = false; </span> <span>for (var i = 2; !found && i <= k; ++i) { </span> found <span>= n % i === 0; </span> <span>} </span> <span>if (!found) { </span> <span>postMessage(n.toString()); </span> <span>} </span> <span>} </span><span>})(2, 1e10); </span>kita juga boleh mengembalikan fungsi yang mengandungi logik pembersihan dari fungsi penciptaan yang dapat dilihat.
Melanggan yang boleh dilihat adalah bebas daripada jenis yang dapat dilihat. Bagi kedua -dua jenis, kami dapat menyediakan tiga fungsi yang memenuhi keperluan asas tatabahasa pemberitahuan yang terdiri daripada OnNext, OneRor, dan OnCompleted. Panggilan balik OnNext adalah wajib.
<span>var worker = new Worker('prime.js'); </span>worker<span>.addEventListener('message', function (ev) { </span> <span>var primeNumber = ev.data * 1; </span> <span>console.log(primeNumber); </span><span>}, false); </span>sebagai amalan terbaik kita harus menamatkan langganan dengan menggunakan kaedah pelupusan. Ini akan melakukan apa -apa langkah pembersihan yang diperlukan. Jika tidak, mungkin untuk mengelakkan pengumpulan sampah daripada membersihkan sumber yang tidak digunakan.
tanpa melanggan yang boleh dilihat yang terkandung dalam pembolehubah yang boleh dilihat hanya dapat dilihat sejuk. Walau bagaimanapun, ia juga mungkin untuk menukarnya ke urutan panas (iaitu, kami melakukan langganan pseudo) menggunakan kaedah penerbitan.
<span>(function (start<span>, end</span>) { </span> <span>var n = start - 1; </span> <span>while (n++ < end) { </span> <span>var k = Math.sqrt(n); </span> <span>var found = false; </span> <span>for (var i = 2; !found && i <= k; ++i) { </span> found <span>= n % i === 0; </span> <span>} </span> <span>if (!found) { </span> <span>postMessage(n.toString()); </span> <span>} </span> <span>} </span><span>})(2, 1e10); </span>
Beberapa pembantu yang terkandung dalam RXJS hanya berurusan dengan penukaran struktur data sedia ada. Di JavaScript kita boleh membezakan antara tiga daripadanya:
yang terakhir adalah baru dengan ES6 dan boleh digantikan dengan tatasusunan (walaupun itu pengganti yang buruk dan harus dianggap sebagai satu nilai) untuk ES5 atau lebih tua.
rxjs kini membawa datatype untuk menyediakan sokongan nilai berganda (pulangan) yang tidak segerak. Oleh itu, empat kuadran kini diisi.
<span>var worker = new Worker('prime.js'); </span>worker<span>.addEventListener('message', function (ev) { </span> <span>var primeNumber = ev.data * 1; </span> <span>console.log(primeNumber); </span><span>}, false); </span>Kebanyakan pembantu yang membuat atau berurusan dengan Observables juga menerima penjadual, yang mengawal apabila langganan bermula dan apabila pemberitahuan diterbitkan. Kami tidak akan pergi ke butiran di sini kerana penjadual lalai berfungsi dengan baik untuk tujuan yang paling praktikal.
Banyak pengendali dalam RXJs memperkenalkan kesesuaian, seperti pendikit, selang, atau kelewatan. Sekarang kita akan melihat lagi contoh -contoh sebelumnya, di mana pembantu ini menjadi penting.
Contoh
di sini, kita sebenarnya mungkin mahu menggunakan fungsi penampan RXJS bersempena dengan pembantu selang yang telah disebutkan sebelumnya.
Hasilnya hendaklah diwakili oleh rajah berikut. Gumpalan hijau timbul selepas selang masa yang ditentukan (diberikan oleh masa yang digunakan untuk membina selang). Penampan akan mengagregatkan semua gumpalan biru yang dilihat semasa selang waktu.
Selain itu, kami juga boleh memperkenalkan Peta, yang membantu kami mengubah data. Sebagai contoh, kami mungkin mahu mengubah hujah -hujah acara yang diterima untuk mendapatkan data yang dihantar sebagai nombor.
Fungsi Ofevent membina yang dapat dilihat dari mana -mana objek menggunakan corak pemancar peristiwa standard. Penampan juga akan mengembalikan array dengan sifar panjang, itulah sebabnya kami memperkenalkan fungsi di mana untuk mengurangkan aliran ke array yang tidak kosong. Akhirnya, dalam contoh ini kita hanya berminat dengan bilangan nombor perdana yang dihasilkan. Oleh itu, kami memetakan penampan untuk mendapatkan panjangnya.
<span>var observable = Rx.<span>Observable</span>.create(function (observer) { </span> observer<span>.onNext(42); </span> observer<span>.onCompleted(); </span><span>}); </span>
Contoh lain ialah kotak pertanyaan carian, yang harus diletakkan untuk memulakan permintaan selepas masa terbiar tertentu. Terdapat dua fungsi yang mungkin berguna dalam senario sedemikian: fungsi pendikit menghasilkan entri pertama yang dilihat dalam tetingkap masa yang ditentukan. Fungsi debounce menghasilkan entri terakhir yang dilihat dalam tetingkap masa yang ditentukan. Tingkap masa juga beralih dengan sewajarnya (iaitu, berbanding dengan item pertama / terakhir).
Kami ingin mencapai tingkah laku yang dicerminkan oleh rajah berikut. Oleh itu, kita akan menggunakan mekanisme debounce.
<span>(function (start<span>, end</span>) { </span> <span>var n = start - 1; </span> <span>while (n++ < end) { </span> <span>var k = Math.sqrt(n); </span> <span>var found = false; </span> <span>for (var i = 2; !found && i <= k; ++i) { </span> found <span>= n % i === 0; </span> <span>} </span> <span>if (!found) { </span> <span>postMessage(n.toString()); </span> <span>} </span> <span>} </span><span>})(2, 1e10); </span>Dalam kod ini tetingkap ditetapkan kepada 300ms. Juga kami menyekat pertanyaan untuk nilai dengan sekurang -kurangnya 3 aksara, yang berbeza dari pertanyaan sebelumnya. Ini menghapuskan permintaan yang tidak perlu untuk input yang baru saja diperbetulkan dengan menaip sesuatu dan memadamkannya.
Terdapat dua bahagian penting dalam keseluruhan ungkapan ini. Satu adalah transformasi teks pertanyaan kepada permintaan menggunakan Searchfor, yang lain adalah fungsi Switch (). Yang terakhir mengambil sebarang fungsi yang mengembalikan pemerhatian bersarang dan menghasilkan nilai hanya dari urutan yang paling terkini.
Fungsi untuk membuat permintaan boleh ditakrifkan seperti berikut:
<span>var worker = new Worker('prime.js'); </span>worker<span>.addEventListener('message', function (ev) { </span> <span>var primeNumber = ev.data * 1; </span> <span>console.log(primeNumber); </span><span>}, false); </span>Perhatikan yang boleh diperhatikan bersarang (yang mungkin mengakibatkan tidak ditentukan untuk permintaan yang tidak sah) itulah sebabnya kami berantai suis () dan di mana ().
KESIMPULAN
di mana anda melihat rxjs bersinar?
Bagaimana saya mengendalikan kesilapan dalam rxjs?
RXJS menyediakan beberapa pengendali untuk mengendalikan kesilapan, seperti CatchError dan Retry. Operator CatchError menangkap ralat pada sumber yang dapat dilihat dan meneruskan aliran dengan baru yang dapat dilihat atau ralat. Operator Retry Resubscribes ke sumber yang dapat dilihat apabila gagal. ',' penapis ',' concat ',' mengurangkan ', dan lain -lain. Terdapat berpuluh -puluh pengendali yang terdapat dalam RXJ yang boleh digunakan untuk mengendalikan manipulasi koleksi yang kompleks, sama ada mereka adalah tatasusunan item, aliran peristiwa, atau bahkan janji.
Atas ialah kandungan terperinci Pengenalan kepada pengaturcaraan reaktif berfungsi dengan RXJS. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!