pengaturcaraan asynchronous node.js: pemahaman mendalam mengenai gelung acara
javascript adalah satu-threaded, tetapi adakah ini mengehadkan keupayaan node.js untuk memanfaatkan arsitektur moden? Salah satu cabaran terbesar adalah berurusan dengan kerumitan multithreading yang wujud. Mewujudkan benang baru dan menguruskan konteks beralih antara benang adalah mahal. Kedua -dua sistem operasi dan pengaturcara memerlukan banyak usaha untuk menyediakan penyelesaian yang mengendalikan pelbagai kes kelebihan. Artikel ini akan menjelaskan bagaimana Node.js menyelesaikan masalah ini melalui gelung acara, meneroka pelbagai aspek gelung acara Node.js dan menunjukkan bagaimana ia berfungsi. Gelung acara adalah salah satu ciri pembunuh node.js kerana ia menyelesaikan masalah rumit ini dengan cara yang sama sekali baru.
Loop Acara adalah gelung serentak, tidak menyekat dan tidak segerak. Bagi seseorang tanpa ijazah sains komputer, bayangkan permintaan web yang melakukan carian pangkalan data. Satu benang hanya boleh melakukan satu operasi pada satu masa. Daripada menunggu pangkalan data untuk bertindak balas, ia terus memproses tugas lain dalam barisan. Dalam gelung acara, gelung utama memperluaskan timbunan panggilan dan tidak menunggu panggilan balik. Oleh kerana gelung tidak menyekat, ia boleh mengendalikan pelbagai permintaan web secara serentak. Permintaan berganda boleh dihukum pada masa yang sama, menjadikannya serentak. Gelung tidak menunggu semua operasi permintaan selesai, tetapi diproses mengikut urutan di mana panggilan balik berlaku tanpa menyekat.
Gelung itu sendiri adalah separa infinit, yang bermaksud bahawa ia boleh keluar dari gelung jika timbunan panggilan atau giliran panggilan balik kosong. Tumpukan panggilan boleh dianggap sebagai kod segerak, seperti Console.log, berkembang sebelum gelung untuk mengundi lebih banyak kerja. Node.js menggunakan libuv yang mendasari untuk mengundi sistem operasi untuk panggilan balik dari sambungan masuk.
anda mungkin tertanya -tanya, mengapa gelung acara dilaksanakan dalam satu benang? Benang lebih berat dalam ingatan untuk data yang diperlukan untuk setiap sambungan. Threads adalah sumber sistem operasi yang perlu dimulakan, yang tidak dapat dilanjutkan kepada beribu -ribu sambungan aktif.
Biasanya, multithreading juga boleh merumitkan keadaan. Sekiranya panggilan balik mengembalikan data, ia mesti marshal konteks kembali ke benang yang dilaksanakan. Konteks beralih antara benang adalah perlahan kerana ia mesti menyegerakkan keadaan semasa, seperti timbunan panggilan atau pembolehubah tempatan. Gelung peristiwa boleh mengelakkan pepijat apabila pelbagai thread berkongsi sumber kerana ia adalah satu berulir. Gelung tunggal-threaded mengurangkan kes-kes kelebihan benang yang selamat dan membolehkan penukaran konteks yang lebih cepat. Ini adalah jenius sebenar di belakang gelung. Ia berkesan menggunakan sambungan dan benang sambil mengekalkan skalabiliti.
Teori sudah cukup; Anda boleh melakukannya dalam Repl seperti yang anda suka atau memuat turun kod sumber.
Persoalan terbesar yang mesti dijawab oleh gelung acara adalah sama ada gelung itu aktif. Jika ya, tentukan berapa lama menunggu pada giliran panggilan balik. Dalam setiap lelaran, Loop memperluaskan timbunan panggilan dan pemilihan.
Ini adalah contoh menghalang gelung utama:
setTimeout( () => console.log('Hi from the callback queue'), 5000); // 保持循环活动这么长时间 const stopTime = Date.now() + 2000; while (Date.now() < stopTime) {}
Jika anda menjalankan kod ini, perhatikan bahawa gelung disekat selama dua saat. Walau bagaimanapun, gelung tetap aktif sehingga panggilan balik dilaksanakan selepas lima saat. Sebaik sahaja gelung utama tidak disekat, mekanisme pengundian menentukan berapa lama ia akan menunggu panggilan balik. Gelung ini berakhir apabila timbunan panggilan berkembang dan tidak ada panggilan balik.
Sekarang, apa yang berlaku apabila saya menyekat gelung utama dan kemudian menjadualkan panggilan balik? Sebaik sahaja gelung disekat, ia tidak menambah lebih banyak panggilan balik ke barisan:
const stopTime = Date.now() + 2000; while (Date.now() < stopTime) {} // 这需要 7 秒才能执行 setTimeout(() => console.log('Ran callback A'), 5000);
Kitaran ini tetap aktif selama tujuh saat. Gelung acara adalah bodoh dari segi kesederhanaan mereka. Ia tidak mempunyai cara untuk mengetahui apa yang mungkin beratur pada masa akan datang. Dalam sistem sebenar, panggilan balik masuk adalah beratur dan dilaksanakan apabila gelung utama boleh ditinjau. Gelung acara berjalan melalui beberapa peringkat dalam urutan apabila menyekat. Oleh itu, untuk menonjol dalam wawancara mengenai gelung, elakkan istilah mewah seperti "Pelancar Acara" atau "Mod Reaktor". Ia adalah gelung tunggal yang mudah, serentak dan tidak menyekat. gelung acara menggunakan async/menunggu
Apa -apa yang muncul selepas menunggu datang dari giliran panggil balik. Kod ini kelihatan seperti kod menyekat segerak, tetapi ia tidak menyekat. Ambil perhatian bahawa async/menunggu membuat ReadFileSync a
const fs = require('fs'); const readFileSync = async (path) => await fs.readFileSync(path); readFileSync('readme.md').then((data) => console.log(data)); console.log('The event loop continues without blocking...');
, yang menghilangkannya dari gelung utama. Apa-apa sahaja yang muncul selepas menunggu boleh dianggap sebagai operasi yang tidak menyekat melalui panggilan balik. Pendedahan penuh: Kod di atas adalah untuk tujuan demonstrasi sahaja. Dalam kod sebenar, saya cadangkan menggunakan fs.readfile, yang mencetuskan panggilan balik yang boleh dibungkus janji. Niat keseluruhan tetap sah kerana ini akan menyekat penyingkiran I/O dari gelung utama.
pergi lebih jauh
Sekarang, saya ingin membawa anda lebih mendalam ke dalam node.js.
Kemas kini Timestamp. Gelung acara cache pada masa semasa pada permulaan gelung untuk mengelakkan panggilan sistem yang sering berkaitan dengan masa. Panggilan sistem ini adalah panggilan dalaman kepada libuv.
setTimeout( () => console.log('Hi from the callback queue'), 5000); // 保持循环活动这么长时间 const stopTime = Date.now() + 2000; while (Date.now() < stopTime) {}
Anda mungkin tidak begitu akrab dengan C, tetapi ini berbunyi seperti bahasa Inggeris dan sama seperti yang diterangkan dalam Fasa 7.
untuk memaparkan setiap peringkat dengan JavaScript tulen:
const stopTime = Date.now() + 2000; while (Date.now() < stopTime) {} // 这需要 7 秒才能执行 setTimeout(() => console.log('Ran callback A'), 5000);
Kerana fail I/O Fail I/O berjalan sebelum Peringkat 4 dan 9, diharapkan setimmediate () akan membakar terlebih dahulu:
const fs = require('fs'); const readFileSync = async (path) => await fs.readFileSync(path); readFileSync('readme.md').then((data) => console.log(data)); console.log('The event loop continues without blocking...');
Rangkaian I/O tanpa pertanyaan DNS lebih murah daripada fail I/O kerana ia dijalankan dalam gelung acara utama. Fail I/O beratur melalui kolam benang. Pertanyaan DNS juga menggunakan kolam thread, jadi ini menjadikan rangkaian I/O sebagai mahal seperti Fail I/O.
node.js mempunyai dua bahagian utama: enjin V8 JavaScript dan libuv. Fail I/O, pertanyaan DNS, dan rangkaian I/O dilakukan melalui libuv.
ini adalah struktur keseluruhan:
Sumber gambar: Dokumen libuv
untuk rangkaian I/O, pengundian gelung acara dalam benang utama. Benang ini tidak selamat benang kerana ia tidak mempunyai suis konteks dengan benang lain. Fail I/O dan pertanyaan DNS adalah platform khusus, jadi kaedahnya adalah untuk menjalankannya dalam kolam thread. Satu idea ialah melakukan pertanyaan DNS untuk mengelakkan memasuki kolam thread, seperti yang ditunjukkan dalam kod di atas. Sebagai contoh, memasukkan alamat IP dan bukannya localhost menghilangkan carian dari kolam. Bilangan benang yang terdapat di kolam thread adalah terhad dan boleh ditetapkan melalui pembolehubah persekitaran UV_THREADPOOL_SIZE. Saiz kolam thread lalai adalah kira -kira empat.V8 dilaksanakan dalam gelung yang berasingan, membersihkan timbunan panggilan, dan mengembalikan kawalan ke gelung acara. V8 boleh menggunakan pelbagai benang untuk pengumpulan sampah di luar gelungnya sendiri. Fikirkan V8 sebagai enjin yang mengambil JavaScript asal dan menjalankannya pada perkakasan.
Untuk pengaturcara biasa, JavaScript tetap menjadi satu-satunya kerana tidak ada masalah keselamatan benang. V8 dan Libuv secara dalaman memulakan benang berasingan mereka sendiri untuk memenuhi keperluan mereka sendiri.
Jika terdapat masalah throughput dalam node.js, mulakan dengan gelung acara utama. Semak berapa lama masa yang diperlukan untuk melengkapkan lelaran tunggal. Ia tidak boleh melebihi seratus milisaat. Kemudian, periksa kelaparan kolam renang dan apa yang boleh diusir dari kolam. Saiz kolam juga boleh ditingkatkan oleh pembolehubah persekitaran. Langkah terakhir adalah untuk melaksanakan mikrobenchmarking kod JavaScript dalam Synchronously dilaksanakan V8.
Ringkasan
process.nexttick () dan setImmediate ()
Beberapa sebab mengapa anda mungkin memerlukan proses.NextTick ():
Sebagai contoh, pemancar acara mahu mencetuskan peristiwa dalam pembina sendiri. Tumpukan panggilan mesti diperluas sebelum acara boleh dipanggil.
setTimeout( () => console.log('Hi from the callback queue'), 5000); // 保持循环活动这么长时间 const stopTime = Date.now() + 2000; while (Date.now() < stopTime) {}
Membenarkan pengembangan stack panggilan menghalang kesilapan seperti RangeError: Saiz timbunan panggilan maksimum melebihi. Satu perkara yang perlu diperhatikan ialah memastikan proses.NextTick () tidak menghalang gelung acara. Panggilan balik rekursif dalam peringkat yang sama boleh menyebabkan masalah menyekat.
gelung acara merangkumi kesederhanaan dalam kerumitan muktamadnya. Ia menyelesaikan masalah yang sukar seperti asynchronicity, keselamatan benang, dan kesesuaian. Ia menghilangkan bahagian yang tidak berguna atau tidak diingini dan memaksimumkan throughput dengan cara yang paling berkesan. Oleh itu, pengaturcara Node.js dapat mengurangkan masa untuk mengejar kesilapan tak segerak dan menghabiskan lebih banyak masa untuk menyampaikan ciri -ciri baru.
Apakah gelung acara Node.js? Gelung peristiwa Node.js adalah mekanisme teras yang membolehkan Node.js melakukan operasi tak segerak yang tidak menyekat. Ia bertanggungjawab untuk mengendalikan operasi I/O, pemasa, dan panggilan balik dalam persekitaran yang didorong oleh acara tunggal.
bagaimana gelung acara nod berfungsi? Gelung acara terus memeriksa untuk acara atau panggilan balik dalam barisan acara dan melaksanakannya mengikut urutan tambahan. Ia berjalan dalam gelung, mengendalikan peristiwa berdasarkan ketersediaan peristiwa, yang menjadikan pengaturcaraan tak segerak dalam node.js mungkin.
Apakah peranan gelung acara dalam aplikasi Node.js? Gelung acara berada di tengah -tengah node.js, yang memastikan aplikasi tetap responsif dan dapat mengendalikan banyak sambungan serentak tanpa beberapa benang.
Apakah peringkat gelung acara Node.js? Gelung acara di Node.js mempunyai beberapa peringkat, termasuk pemasa, panggilan balik yang belum selesai, terbiar, mengundi, memeriksa, dan menutup. Fasa -fasa ini menentukan bagaimana dan memerintahkan peristiwa diproses.
Apakah jenis acara yang paling biasa yang diproses oleh gelung acara? Acara umum termasuk operasi I/O (contohnya, membaca dari fail atau mengeluarkan permintaan rangkaian), pemasa (contohnya, setTimeout dan setInterval), dan fungsi panggilan balik (contohnya, panggilan balik dari operasi tak segerak).
nod Bagaimana menangani operasi jangka panjang dalam gelung acara? Operasi intensif CPU yang lama boleh menghalang gelung acara dan harus dimuatkan ke dalam proses kanak-kanak atau benang pekerja menggunakan modul seperti modul Child_Process atau Worker_Threads.
Apakah perbezaan antara timbunan panggilan dan gelung acara? Tumpukan panggilan adalah struktur data yang menjejaki fungsi panggilan dalam konteks pelaksanaan semasa, sementara gelung acara bertanggungjawab untuk menguruskan operasi asynchronous dan tidak menyekat. Mereka bekerjasama kerana peristiwa gelung acara pelaksanaan panggilan balik dan operasi I/O, dan kemudian menolaknya ke timbunan panggilan.
Apakah "tanda" dalam gelung acara? "Tick" merujuk kepada satu lelaran gelung acara. Dalam setiap tanda, pemeriksaan gelung acara untuk acara yang belum selesai dan melaksanakan sebarang panggilan balik yang sedia untuk dijalankan. Ticks adalah unit asas kerja dalam aplikasi Node.js.
Atas ialah kandungan terperinci The Node.js Event Loop: Panduan Pemaju ' s Konsep & Kod. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!