Saya memikirkannya dan inilah yang saya pikirkan:
Katakanlah kita memiliki kode seperti ini:
console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);
Permintaan masuk, dan mesin JS mulai mengeksekusi kode di atas langkah demi langkah. Dua panggilan pertama adalah panggilan sinkronisasi. Tetapi ketika datang ke setTimeout
metode, itu menjadi eksekusi async. Tetapi JS segera kembali darinya dan melanjutkan eksekusi, yang disebut Non-Blocking
atau Async
. Dan itu terus bekerja pada yang lain dll.
Hasil dari eksekusi ini adalah sebagai berikut:
acdb
Jadi pada dasarnya yang kedua setTimeout
diselesaikan terlebih dahulu dan fungsi callback dijalankan lebih awal dari yang pertama dan itu masuk akal.
Kita berbicara tentang aplikasi single-threaded di sini. JS Engine terus menjalankan ini dan kecuali itu menyelesaikan permintaan pertama, itu tidak akan pergi ke yang kedua. Tetapi hal baiknya adalah bahwa ia tidak akan menunggu untuk memblokir operasi yang ingin setTimeout
diselesaikan sehingga akan lebih cepat karena menerima permintaan masuk yang baru.
Tetapi pertanyaan saya muncul di sekitar item berikut:
# 1: Jika kita berbicara tentang aplikasi single-threaded, lalu mekanisme apa yang diproses setTimeouts
saat mesin JS menerima lebih banyak permintaan dan menjalankannya? Bagaimana utas tunggal terus bekerja pada permintaan lain? Apa yang berfungsi setTimeout
saat permintaan lainnya terus masuk dan dieksekusi.
# 2: Jika setTimeout
fungsi - fungsi ini dieksekusi di belakang layar saat lebih banyak permintaan masuk dan dieksekusi, apa yang melakukan eksekusi async di belakang layar? Benda apa yang kita bicarakan ini disebut EventLoop
?
# 3: Tapi bukankah seluruh metode harus dimasukkan EventLoop
sehingga semuanya dieksekusi dan metode panggilan balik dipanggil? Inilah yang saya mengerti ketika berbicara tentang fungsi callback:
function downloadFile(filePath, callback)
{
blah.downloadFile(filePath);
callback();
}
Tetapi dalam kasus ini, bagaimana JS Engine tahu jika itu adalah fungsi async sehingga dapat menempatkan panggilan balik dalam EventLoop? Perhaps something like the
kata kunci async` dalam C # atau semacam atribut yang menunjukkan metode yang akan diambil oleh Mesin JS adalah metode async dan harus diperlakukan sebagaimana mestinya.
# 4: Tapi sebuah artikel mengatakan sangat bertentangan dengan apa yang saya duga tentang bagaimana segala sesuatunya bekerja:
Loop Peristiwa adalah antrian fungsi panggilan balik. Ketika fungsi async dijalankan, fungsi callback didorong ke antrian. Mesin JavaScript tidak mulai memproses loop acara hingga kode setelah fungsi async dijalankan.
# 5: Dan ada gambar ini di sini yang mungkin bisa membantu tetapi penjelasan pertama dalam gambar mengatakan hal yang persis sama yang disebutkan dalam pertanyaan nomor 4:
Jadi pertanyaan saya di sini adalah untuk mendapatkan klarifikasi tentang barang-barang yang tercantum di atas?
Jawaban:
Hanya ada 1 utas dalam proses simpul yang benar-benar akan menjalankan JavaScript program Anda. Namun, di dalam node itu sendiri, sebenarnya ada beberapa thread yang menangani operasi dari mekanisme loop event, dan ini termasuk kumpulan thread IO dan beberapa lainnya. Kuncinya adalah jumlah utas ini tidak sesuai dengan jumlah koneksi konkurensi yang ditangani seperti yang akan mereka lakukan dalam model konkurensi thread-per-koneksi.
Sekarang tentang "mengeksekusi setTimeouts", ketika Anda memohon
setTimeout
, semua node tidak pada dasarnya memperbarui struktur data fungsi yang akan dieksekusi pada suatu waktu di masa depan. Ini pada dasarnya memiliki banyak antrian hal-hal yang perlu dilakukan dan setiap "centang" dari loop acara yang dipilihnya, menghapusnya dari antrian, dan menjalankannya.Hal utama yang harus dipahami adalah simpul bergantung pada OS untuk sebagian besar pengangkatan berat. Jadi permintaan jaringan yang masuk sebenarnya dilacak oleh OS itu sendiri dan ketika node siap untuk menangani itu hanya menggunakan panggilan sistem untuk meminta OS untuk permintaan jaringan dengan data siap untuk diproses. Begitu banyak simpul "kerja" IO yang berfungsi sebagai "Hai OS, dapatkan koneksi jaringan dengan data yang siap dibaca?" atau "Hai OS, apakah panggilan sistem file saya yang luar biasa sudah siap data?". Berdasarkan algoritma internal dan desain mesin acara loop, node akan memilih satu "centang" dari JavaScript untuk dieksekusi, jalankan, lalu ulangi proses dari awal lagi. Itulah yang dimaksud dengan loop acara. Node pada dasarnya setiap saat menentukan "apa yang harus saya jalankan JavaScript selanjutnya," kemudian jalankan.
setTimeout
atauprocess.nextTick
.Tidak ada JavaScript yang dieksekusi di belakang layar. Semua JavaScript di program Anda berjalan di depan dan tengah, satu per satu. Apa yang terjadi di belakang layar adalah OS menangani IO dan node menunggu untuk siap dan node mengelola antrian javascript yang menunggu untuk dieksekusi.
Ada satu set fungsi tetap dalam inti simpul yang async karena mereka membuat panggilan sistem dan simpul tahu yang mana ini karena mereka harus memanggil OS atau C ++. Pada dasarnya semua jaringan dan sistem file IO serta interaksi proses anak akan tidak sinkron dan satu-satunya cara JavaScript bisa mendapatkan node untuk menjalankan sesuatu secara tidak sinkron adalah dengan memanggil salah satu fungsi async yang disediakan oleh perpustakaan inti node. Bahkan jika Anda menggunakan paket npm yang mendefinisikan API itu sendiri, untuk menghasilkan loop peristiwa, akhirnya kode paket npm akan memanggil salah satu fungsi async inti node dan saat itulah simpul tahu centang sudah selesai dan dapat memulai acara algoritma loop lagi.
Ya, ini benar, tetapi menyesatkan. Kuncinya adalah pola normal adalah:
Jadi ya, Anda benar-benar dapat memblokir loop peristiwa dengan hanya menghitung angka Fibonacci secara bersamaan semua dalam memori semua dalam centang yang sama, dan ya itu benar-benar akan membekukan program Anda. Ini konkurensi kerja sama. Setiap centang JavaScript harus menghasilkan loop peristiwa dalam jumlah waktu yang wajar atau keseluruhan arsitektur gagal.
sumber
process.nextTick
vssetTimeout
vssetImmediate
agak berbeda, meskipun Anda tidak harus benar-benar peduli. Saya memiliki posting blog yang disebut setTimeout dan teman - teman yang lebih detail.Ada tutorial video yang fantastis oleh Philip Roberts, yang menjelaskan loop peristiwa javascript dengan cara yang paling sederhana dan konseptual. Setiap pengembang javascript harus melihatnya.
Berikut ini tautan video di Youtube.
sumber
Jangan mengira proses host menjadi single-threaded, mereka tidak. Apa yang single-threaded adalah bagian dari proses host yang mengeksekusi kode javascript Anda.
Kecuali untuk pekerja latar belakang , tetapi ini menyulitkan skenario ...
Jadi, semua kode js Anda berjalan di utas yang sama, dan tidak ada kemungkinan bahwa Anda mendapatkan dua bagian berbeda dari kode js Anda untuk berjalan secara bersamaan (jadi, Anda tidak dapat mengelola concurrency nigthmare).
Kode js yang mengeksekusi adalah kode terakhir yang diambil oleh proses host dari loop acara. Dalam kode Anda, pada dasarnya Anda dapat melakukan dua hal: menjalankan instruksi yang sinkron, dan menjadwalkan fungsi yang akan dieksekusi di masa depan, ketika beberapa peristiwa terjadi.
Inilah representasi mental saya (berhati-hatilah: hanya saja, saya tidak tahu detail penerapan browser!) Dari kode contoh Anda:
Ketika kode Anda sedang berjalan, utas lain dalam proses host melacak semua peristiwa sistem yang terjadi (klik pada UI, membaca file, paket jaringan yang diterima dll.)
Ketika kode Anda selesai, itu dihapus dari loop acara, dan proses host kembali untuk memeriksanya, untuk melihat apakah ada lebih banyak kode untuk dijalankan. Event loop berisi dua event handler lebih: satu untuk dieksekusi sekarang (fungsi justNow), dan satu lagi dalam satu detik (fungsi inAWhile).
Proses host sekarang mencoba untuk mencocokkan semua peristiwa yang terjadi untuk melihat apakah ada penangan terdaftar untuk mereka. Ditemukan bahwa peristiwa yang baru saja ditunggu-tunggu telah terjadi, sehingga mulai menjalankan kodenya. Saat justNow keluar dari fungsi, ia memeriksa perulangan acara di lain waktu, menunjukkan adanya penangan pada acara. Andaikata 1 s telah lewat, ia menjalankan fungsi inAWhile, dan seterusnya ....
sumber