Rumah > hujung hadapan web > tutorial js > Chunk-Busters: Jangan melintasi Strim!

Chunk-Busters: Jangan melintasi Strim!

Linda Hamilton
Lepaskan: 2024-12-02 05:00:10
asal
839 orang telah melayarinya

⚠️ Jika anda mempunyai fotosensitiviti, anda mungkin mahu melangkau ini.
Lihat imej statik di bawah, lampu tersebut akan mula berkelip dengan pantas!

Chunk-Busters: Don’t cross the Streams!

Bagaimanakah internet berfungsi?

Ingat tajuk… kita bercakap tentang strim di sini.

Saya boleh bercakap tentang protokol, paket, pesanan, acks dan nacks… tetapi kita bercakap tentang strim di sini, dan seperti yang anda mungkin sangka betul (saya percaya pada anda =D) dengan strim… ia sama ada binari atau rentetan.

Ya, rentetan dizip sebelum dihantar… tetapi untuk perkara yang biasanya kami ambil berat dalam pembangunan bahagian hadapan dan belakang... rentetan dan binari.

Dalam contoh berikut, saya akan menggunakan strim JS.

Walaupun Node mempunyai pelaksanaan warisannya sendiri, kami mempunyai cara untuk menangani strim yang mempunyai kod yang sama, sama ada di hadapan atau belakang.

Bahasa lain mempunyai cara mereka menangani strim, tetapi seperti yang anda akan lihat... bahagian kod sebenar menanganinya tidaklah begitu rumit (bukan untuk mengatakan tiada perkara rumit berlaku).

Masalah contoh

Anda mempunyai bahagian hadapan yang perlu menggunakan data daripada berbilang sumber.

Walaupun anda boleh mengakses setiap sumber secara individu melalui IP/portnya, anda meletakkannya di belakang Gerbang API untuk kemudahan penggunaan dan kawalan.

Repo

Semak repo di pautan, di sana pelajari cara menjalankannya sendiri supaya anda boleh bermain dengannya.

https://github.com/Noriller/chunk-busters

Video

Versi video untuk diikuti:

https://youtu.be/QucaOfFI0fM

v0 - pelaksanaan naif

Anda mempunyai sumber, anda ambil, tunggu dan render. Bilas dan ulangi.

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
Salin selepas log masuk
Salin selepas log masuk

Anda mungkin berfikir bahawa tiada siapa yang akan melakukannya…

Dalam contoh ini, jelas bahawa ada sesuatu yang tidak kena, tetapi tidaklah sukar untuk terlibat dalam perkara ini.

Yang jelas: ia perlahan. Anda perlu menembak dan menunggu setiap permintaan dan jika ia lambat… anda perlu menunggu.

v1 - versi bersemangat

Anda tahu anda tidak mahu menunggu setiap permintaan secara individu... jadi anda memadamkan semua dan kemudian tunggu sehingga permintaan itu selesai.

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
Salin selepas log masuk
Salin selepas log masuk

Inilah yang mungkin anda lakukan, jadi ia bagus bukan?

Maksud saya, kecuali jika anda mempunyai SATU permintaan yang lambat... ini bermakna walaupun semua yang lain sudah selesai… anda masih perlu menunggu untuk selesai.

v2 - versi yang lebih bijak, bersemangat

Anda tahu anda mungkin mempunyai beberapa permintaan yang lebih perlahan, jadi anda masih memadamkan semua dan menunggu, tetapi apabila ia datang, anda sudah melakukan sesuatu dengan hasilnya apabila boleh, jadi apabila yang terakhir tiba, yang lain sudah selesai.

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
Salin selepas log masuk
Salin selepas log masuk

Ini MESTI menjadi penyelesaian terbaik bukan?

Hmm... sesuatu yang pelik?

v3 - Saya berbohong kepada anda... inilah yang sepatutnya kelihatan seperti v1

Ingat v1? Ya… beginilah rupanya:

Ternyata terdapat had kepada bilangan sambungan yang boleh anda miliki dengan titik akhir yang sama dalam http/1 dan bukan itu sahaja… ia bergantung kepada penyemak imbas dan setiap penyemak imbas mungkin mempunyai had yang berbeza.

Anda mungkin terfikir untuk hanya menggunakan http/2 dan memanggilnya sehari… tetapi walaupun ini penyelesaian yang baik, anda masih perlu berurusan dengan berbilang titik akhir di bahagian hadapan.

Adakah terdapat penyelesaian yang baik untuk ini?

v4 - masukkan strim!

Mari kita lihat semula v0 tetapi menggunakan strim…

Anda bijak, jadi anda mungkin menjangkakan perkara ini memandangkan amaran itu merosakkannya sedikit… tetapi ya... apa yang anda lihat sebelum ini bukanlah semua data yang dijana oleh bahagian belakang.

Bagaimanapun... semasa kami mengambil kami membuat persembahan.

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
Salin selepas log masuk
Salin selepas log masuk

Sebaliknya, jika kita mengetik pada strim yang akan datang, kita boleh melakukan sesuatu dengan sebahagian daripada data yang datang. (Ya! Suka Sembang GPT dan seumpamanya lakukan.)

Walaupun v0 adalah cara paling teruk untuk menangani masalah ini, ia dapat dipertingkatkan dengan menggunakan strim. Anda boleh menipu pengguna dengan menunjukkan sesuatu, apa sahaja, walaupun jumlah masa menunggu adalah sama.

v5 - v1, sekali lagi, tetapi dengan aliran!

Masalah http/1 masih menjadi isu, tetapi sekali lagi, anda sudah boleh melihat perkara itu apabila ia datang.

Ya… Saya tidak boleh menahan ini lagi… jadi…

v6 - satu API untuk memerintah mereka semua!

Atau... mungkin saya boleh?

Anda lihat, bahagian hadapan terpaksa mengurus terlalu banyak... jika kami boleh memunggahnya ke bahagian belakang, maka anda boleh mempunyai satu titik akhir yang akan mengendalikan semua sumber.

Ini menyelesaikan kerumitan pada bahagian hadapan dan isu http/1.

await Promise.all([
  fetch1().then(handleResult),
  fetch2().then(handleResult),
  ...
  fetch9().then(handleResult),
]);
Salin selepas log masuk


// usually we do this:
await fetch(...).then((res) => {
  // this json call accumulate all the response
  // that later is returned for you to use
  return res.json()
})
Salin selepas log masuk

v7 - dan akhirnya... satu API, pelbagai sumber dan penstriman.

Kami memanggil satu API, yang akan memanggil semua sumber, menstrim data, mengendalikannya dan menghantarnya ke hadapan yang akan, seterusnya, memaparkan data semasa ia datang.

Kod yang digunakan untuk ini pada asasnya sama di bahagian depan dan belakang:

await fetchAll();
handleAllResults(results);
Salin selepas log masuk

Ya… itu sahaja (seperti contoh yang paling asas dan mudah).

Kami menambahkan rentetan yang datang pada penimbal, menghuraikannya, menyemak sama ada terdapat bahagian yang boleh digunakan, gunakannya dan lupakannya. Ini bermakna anda boleh menerima/mengambil TB data... satu bahagian pada satu masa, dengan sedikit RAM.

Saya tahu apa yang anda fikirkan… dan ia bodoh… ia juga kegilaan…

MOOOOOOOM Saya mahukan Websockets!

Tidak sayang, kami mempunyai soket web di rumah!

Soket web di rumah: seterusnya?

v8 - ia hanya bodoh jika ia tidak berfungsi

Anda bijak, anda fikir jika sumbernya masih menjana data… maka mungkin kami boleh mengemas kini beberapa pembolehubah…

Dengan cara ini anda boleh memastikan satu sambungan digunakan untuk mendapatkan lebih banyak data atau menukar sesuatu daripada apa yang dijanakannya.

Ya... Saya rasa anda boleh melakukannya... dan saya melakukan contoh atas desakan anda. =D

Namun… ia adalah idea yang bodoh, saya tidak tahu di mana/jika ia boleh digunakan dalam persekitaran pengeluaran sebenar. Mungkin jika anda kembali ke masa lalu ke fasa JS yang janggal antara MPA dan Ajax di mana anda mempunyai interaktiviti yang mencukupi, tetapi tidak cukup sambungan ke pelayan yang sama (sesetengah penyemak imbas mempunyai had hanya 2!) maka mungkin?

Selain itu, tiada idea. Jika anda ada… beritahu saya.

Dalam contoh di atas, perhatian kepada papan tengah, terutamanya "sempadan kemajuan": anda dapat melihat bahawa papan itu terus mengemas kini. Jika anda membuka tab rangkaian anda akan melihat bahawa sambungan GET tidak pernah ditutup sebelum tamat. Anda juga akan melihat beberapa permintaan lain yang mengubah perkara yang dilakukan oleh sambungan itu, masih hidup,… semua itu dengan vanila http/1.

Apa yang seterusnya?

String lwn JSON

Contoh ini adalah yang paling asas yang boleh saya buat. Saya juga menggunakan rentetan ringkas dan bukannya JSON kerana ia lebih mudah untuk dihuraikan.

Untuk menggunakan JSON, anda perlu mengumpul rentetan (kami perlu JSON. merangkai respons bahagian belakang atas sebab tertentu).

Kemudian sama ada semak di mana untuk memecahkannya dan kemudian menghuraikan nilai itu atau menghuraikan semasa anda pergi.

Untuk yang pertama, fikirkan NDJSON: bukannya tatasusunan JSON, anda memisahkan objek dengan baris baharu, kemudian anda boleh "lebih mudah" mencari tempat untuk dipecahkan, kemudian JSON.parse setiap satu dan gunakan objek.

Untuk yang terakhir, anda menghuraikan semasa anda pergi seperti dalam: anda tahu anda berada dalam tatasusunan, kini ia objek, ok kekunci pertama, kini nilai kunci, kekunci seterusnya, langkau itu, kekunci seterusnya… dan seterusnya dan seterusnya… ia bukan sesuatu yang remeh untuk dibuat secara manual, tetapi ia seperti lompatan daripada menunggu kemudian berikan kepada render sambil anda menunggu ini semua tentang… kecuali… pada yang lebih kecil skala.

Pengendalian Ralat

Orang suka mengehos contoh, yang ini anda perlu menjalankan sendiri... Saya harap sebab untuk tidak mengehoskan contoh di suatu tempat sudah jelas sekarang, tetapi satu lagi ialah kami tidak menjangkakan sebarang ralat di sini, dan jika anda tambah ralat rangkaian di atas segala-galanya… baik…

Ralat harus ditangani, tetapi ia menambah satu lagi lapisan kerumitan.

Patutkah anda menggunakannya?

Mungkin… anda boleh katakan bergantung...

Terdapat tempat di mana penstriman adalah jawapannya tetapi dalam kebanyakan kes… tunggu json sudah cukup (apatah lagi lebih mudah).

Tetapi pembelajaran tentang strim membuka cara untuk menyelesaikan beberapa masalah, sama ada di bahagian hadapan atau bahagian belakang.

Di bahagian hadapan, anda sentiasa boleh menggunakan ini untuk "menipu" pengguna. Daripada menunjukkan pemutar di mana-mana, anda boleh menunjukkan sesuatu semasa ia datang dan kemudian menunjukkan lebih banyak semasa ia datang, walaupun ia mengambil sedikit masa. Selagi anda tidak menghalang pengguna daripada berinteraksi dengannya… anda juga boleh membuat sesuatu yang "lebih perlahan" daripada sekadar menunjukkan pemutar berasa seperti ia lebih pantas daripada apa-apa sebenarnya lebih pantas .

Di bahagian belakang, anda boleh menjimatkan RAM kerana anda hanya boleh menghuraikan setiap bahagian data semasa ia datang, sama ada dari hadapan, pangkalan data atau apa-apa sahaja di antaranya. Kendalikan data seperti yang diperlukan, dan hantarnya tanpa perlu menunggu keseluruhan muatan yang akan menyebabkannya menimbulkan Ralat OOM (Out of Memory). GB atau TB data… pasti, mengapa tidak?

Outro

Adakah React lambat? Contoh bahagian hadapan keseluruhan ini dilakukan dengan React dan selain daripada perkara "utama" yang berlaku dengan semua "lampu" yang berkelip, terdapat banyak perkara lain yang sedang berlaku.

Ya… jika anda pergi dengan cukup pantas, contoh itu tidak dapat mengikuti dan mula membeku. Tetapi kerana ia dengan mudah beribu-ribu pemaparan berlaku setiap minit… Saya rasa ia sudah mencukupi untuk kebanyakan aplikasi.

Dan, anda sentiasa boleh meningkatkan prestasi: untuk "sempadan kemajuan", saya telah menggunakan nilai tertunda untuk menjadikannya lebih lancar jika anda perlu menyimpan beberapa dalam pemaparan... Saya boleh melakukan ini dan peningkatan prestasi lain untuk "lampu" dan tajuk, tetapi ia hanya akan membuatkan "lampu" berhenti berkelip banyak masa (yang tidak akan membuat demo yang bagus), dan juga garis bawah "elektrik" dalam tajuk tidak akan seperti memang seronok.

Dalam contoh ini, semua "penambahbaikan" itu tidak sesuai, tetapi untuk aplikasi biasa... anda boleh membuatnya mengendalikan banyak perkara. Dan jika anda memerlukan sesuatu yang lebih, maka dalam kes ini gunakan penyelesaian lain.

Kesimpulan

Tambahkan aliran pada senjata anda... ini mungkin bukan penyelesaian mujarab, tetapi ia pasti berguna suatu hari nanti.

Dan jika anda akan melakukan sesuatu dengannya dan mahukan bantuan, baik... mungkin hubungi saya. =P

Atas ialah kandungan terperinci Chunk-Busters: Jangan melintasi Strim!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan