Rumah > hujung hadapan web > tutorial js > The Node.js Event Loop: Panduan Pemaju ' s Konsep & Kod

The Node.js Event Loop: Panduan Pemaju ' s Konsep & Kod

Christopher Nolan
Lepaskan: 2025-02-12 08:36:12
asal
614 orang telah melayarinya

pengaturcaraan asynchronous node.js: pemahaman mendalam mengenai gelung acara

The Node.js Event Loop: A Developer's Guide to Concepts & Code

Pengaturcaraan Asynchronous sangat mencabar dalam mana -mana bahasa pengaturcaraan. Konsep seperti kesesuaian, paralelisme dan kebuntuan membuat jurutera yang paling berpengalaman rumit. Kod yang dilaksanakan secara asynchronously sukar untuk diramal dan sukar untuk dijejaki apabila terdapat pepijat. Walau bagaimanapun, masalah ini tidak dapat dielakkan, kerana pengkomputeran moden mempunyai pemproses pelbagai teras. Setiap teras CPU mempunyai had terma tersendiri, dan peningkatan prestasi tunggal teras telah mencapai kesesakan. Ini mendorong pemaju untuk menulis kod yang cekap dan menggunakan sumber perkakasan sepenuhnya.

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.

mata utama

  • gelung acara node.js adalah gelung serentak, tidak menyekat, dan tidak segerak yang membolehkan pelbagai tugas diproses dengan cekap tanpa menunggu setiap tugas selesai. Ini memungkinkan untuk memproses banyak permintaan web secara serentak.
  • Loop acara adalah separa tak terhingga, yang bermaksud ia boleh keluar jika timbunan panggilan atau giliran panggilan balik kosong. Gelung ini bertanggungjawab untuk mengundi sistem operasi untuk mendapatkan panggilan balik dari sambungan masuk.
  • gelung acara berjalan dalam pelbagai peringkat: kemas kini timestamp, pemeriksaan aktiviti gelung, pelaksanaan pemasa, pelaksanaan panggilan balik yang belum selesai, pelaksanaan pengendali terbiar, sediakan mengendalikan untuk pelaksanaan panggil balik setimmediate, hitung waktu pengundian, menyekat I/O, periksa pelaksanaan panggilan balik, tutup Pelaksanaan panggil balik, dan akhir lelaran.
  • node.js menggunakan dua bahagian utama: enjin V8 JavaScript dan libuv. Rangkaian I/O, Fail I/O, dan pertanyaan DNS dilakukan melalui libuv. Bilangan benang yang tersedia untuk tugas -tugas ini di kolam thread adalah terhad dan boleh ditetapkan melalui pembolehubah persekitaran UV_THREADPOOL_SIZE.
  • Pada akhir setiap peringkat, gelung melaksanakan proses. Panggilan balik setimmediate () adalah sebahagian daripada keseluruhan gelung acara, jadi ia tidak dilaksanakan dengan serta -merta sebagai namanya. Secara amnya disyorkan untuk menggunakan setimmediate ().

Apakah gelung acara?

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.

gelung separa infinit

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) {}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

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.

giliran 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);
Salin selepas log masuk
Salin selepas log masuk

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

Untuk mengelakkan menyekat gelung utama, satu idea adalah untuk membungkus I/O segerak dengan 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...');
Salin selepas log masuk
Salin selepas log masuk
thenable

, 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

Bagaimana jika saya memberitahu anda bahawa gelung acara bukan sekadar panggilan susunan dan giliran panggilan balik? Bagaimana jika gelung acara bukan hanya satu gelung, tetapi pelbagai gelung? Bagaimana jika ia boleh mempunyai beberapa benang di bahagian bawah?

Sekarang, saya ingin membawa anda lebih mendalam ke dalam node.js.

Peringkat Loop Event

ini adalah fasa gelung acara:

The Node.js Event Loop: A Developer's Guide to Concepts & Code

Sumber gambar: Dokumen libuv

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.
  1. Adakah gelung aktif? Jika gelung mempunyai pemegang aktif, permintaan aktif, atau pemegang tertutup, ia aktif. Seperti yang ditunjukkan, panggilan balik yang belum selesai dalam barisan menyimpan gelung aktif.
  2. Jalankan pemasa tamat tempoh. Di sinilah SETTimeout atau SetInterval Callback berjalan. Gelung untuk memeriksa CACHED sekarang
  3. untuk membolehkan panggilan balik aktif yang telah tamat tempoh untuk dilaksanakan.
  4. Jalankan panggilan balik yang belum selesai dalam barisan. Sekiranya sebarang panggilan balik ditangguhkan oleh lelaran sebelumnya, panggilan balik ini akan dijalankan pada masa ini. Pengundian biasanya menjalankan panggilan balik I/O segera, dengan pengecualian. Langkah ini mengendalikan sebarang panggilan balik yang tertinggal dari lelaran terakhir.
  5. Jalankan pengendali terbiar -terutamanya kerana penamaan yang tidak betul, kerana pengendali ini berjalan dalam setiap lelaran dan pengendali dalaman untuk libuv.
  6. Sediakan untuk melaksanakan pemegang ke panggil balik setimmediate dalam lelaran gelung. Pemegang ini dijalankan sebelum blok gelung I/O dan menyediakan giliran untuk jenis panggil balik ini.
  7. Kirakan masa pengundian. Gelung mesti tahu apabila ia menyekat I/O. Ini adalah bagaimana ia mengira masa tamat:
  8. Jika gelung hendak keluar, tamat masa adalah 0.
    • Jika tidak ada pemegang atau permintaan aktif, tamat masa adalah 0.
    • Jika terdapat sebarang pemegang percuma, tamat masa adalah 0.
    • Jika ada pegangan yang belum selesai dalam barisan, tamat masa adalah 0.
    • Jika ada pegangan yang sedang ditutup, tamat masa adalah 0.
    • Jika tidak ada di atas, tamat masa ditetapkan pada pemasa yang paling dekat, dan jika tidak ada pemasa aktif, ia adalah
    • tak terhingga
    • .
    • Berbasikal Tempoh blok peringkat sebelumnya I/O. Panggilan balik yang berkaitan dengan I/O di barisan dilaksanakan di sini.
  9. Jalankan panggilan balik Pemegang Semak. Tahap ini adalah tahap larian setimmediate, yang merupakan peringkat yang sepadan untuk menyediakan pemegang. Mana -mana panggilan balik setimmediate yang beratur semasa pelaksanaan panggilan balik I/O akan dijalankan di sini.
  10. Jalankan panggilan balik tertutup. Ini adalah pemegang aktif yang dikeluarkan dari sambungan tertutup.
  11. lelaran berakhir.
  12. Anda mungkin tertanya-tanya mengapa blok pengundian I/O apabila ia sepatutnya tidak menyekat? Gelung hanya akan menyekat apabila tiada panggilan balik yang belum selesai dalam barisan dan timbunan panggilan kosong. Dalam node.js, pemasa terdekat boleh ditetapkan melalui setTimeout, sebagai contoh. Jika ditetapkan ke Infinite, gelung akan menunggu sambungan masuk untuk melakukan lebih banyak kerja. Ini adalah gelung separa infinit kerana pengundian menyimpan gelung aktif apabila tidak ada kerja yang tinggal dan ada sambungan aktif.
Berikut adalah versi UNIX pengiraan masa tamat ini, dalam keseluruhan bentuk kod C:

setTimeout(
  () => console.log('Hi from the callback queue'),
  5000); // 保持循环活动这么长时间

const stopTime = Date.now() + 2000;
while (Date.now() < stopTime) {}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Anda mungkin tidak begitu akrab dengan C, tetapi ini berbunyi seperti bahasa Inggeris dan sama seperti yang diterangkan dalam Fasa 7.

demonstrasi fasa demi tahap

untuk memaparkan setiap peringkat dengan JavaScript tulen:

const stopTime = Date.now() + 2000;
while (Date.now() < stopTime) {}
// 这需要 7 秒才能执行
setTimeout(() => console.log('Ran callback A'), 5000);
Salin selepas log masuk
Salin selepas log masuk

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...');
Salin selepas log masuk
Salin selepas log masuk

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.

Kolam thread

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:

The Node.js Event Loop: A Developer's Guide to Concepts & Code

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

Gelung acara terus melangkah ke atas setiap peringkat kerana panggilan balik beratur. Walau bagaimanapun, dalam setiap peringkat, ada cara untuk beratur satu lagi jenis panggilan balik.

process.nexttick () dan setImmediate ()

Pada akhir setiap peringkat, Process.NextTick () panggil balik dilaksanakan dalam gelung. Perhatikan bahawa jenis panggil balik ini bukan sebahagian daripada gelung acara, kerana ia berjalan pada akhir setiap peringkat. Panggilan balik setimmediate () adalah sebahagian daripada keseluruhan gelung acara, jadi ia tidak dilaksanakan dengan serta -merta sebagai namanya. Oleh kerana Process.NextTick () memerlukan pemahaman tentang mekanisme dalaman gelung peristiwa, saya biasanya mengesyorkan menggunakan setImmediate ().

Beberapa sebab mengapa anda mungkin memerlukan proses.NextTick ():

  1. Benarkan rangkaian I/O untuk mengendalikan kesilapan, membersihkan, atau mencuba permintaan sebelum gelung berterusan.
  2. Mungkin perlu untuk menjalankan panggilan balik selepas timbunan panggilan diperluas tetapi sebelum gelung berterusan.

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) {}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

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.

Kesimpulan

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.

Soalan Lazim Mengenai Node.js Event Loops

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!

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