Artikel ini membawakan kepada anda isu berkaitan tentang mekanisme pelaksanaan JavaScript, termasuk pengetahuan tentang JavaScript single-threading dan penyegerakan JavaScript dan asynchronousness Saya harap ia akan membantu semua orang.
Jika kita ingin memahami mengapa JavaScript adalah satu utas, kita perlu bermula dengan apa JavaScript digunakan untuk lakukan.
Sebagai bahasa skrip untuk penyemak imbas, tujuan JavaScript adalah untuk penyemak imbas berinteraksi dengan pengguna dan mengendalikan elemen DOM, dengan itu meningkatkan interaksi dan pengalaman pengguna. JavaScript perlu mengendalikan elemen DOM penyemak imbas, jadi JavaScript tidak boleh menjadi bahasa berbilang utas Mari kita anggap senario Jika JavaScript ialah bahasa berbilang benang, dua utas mengendalikan elemen DOM pada masa yang sama kemas kini elemen DOM, manakala utas lain perlu mengedit dan mengemas kini elemen DOM Ia adalah untuk memadamkan nod elemen DOM yang mana satu harus digunakan oleh penyemak imbas.
Anda hanya boleh melakukan perkara yang sama pada masa yang sama Kerana manipulasi elemen DOM, satu threading adalah teras dan ciri bahasa JavaScript.
HTML5 mencadangkan piawaian Pekerja Web, yang membenarkan skrip JavaScript membuat berbilang urutan, tetapi urutan anak dikawal sepenuhnya oleh urutan utama dan tidak dibenarkan untuk mengendalikan DOM. Malah perubahan sedemikian tidak mengubah sifat satu benang js.
Mekanisme satu utas JavaScript menyebabkan hanya satu perkara yang boleh dilakukan pada masa yang sama. Sama seperti sekumpulan orang yang mengeluarkan wang dari mesin ATM, walaupun di belakang mereka lebih ramai orang yang tergesa-gesa, mereka hanya boleh beratur seorang demi seorang dan menunggu orang pertama mengeluarkan wang sebelum tiba giliran. daripada orang seterusnya.
Tetapi ini akan menyebabkan jika tugasan sebelumnya mengambil masa terlalu lama, tugasan seterusnya akan menunggu untuk masa yang sangat lama Contohnya, jika kita perlu memuatkan permintaan Ajax dengan jumlah data yang sangat besar, kita perlu menunggu hasil permintaan yang sepadan, dan kemudian terus melaksanakan tugasan berikutnya.
Jadi bagaimana kita harus menghadapi situasi ini? Memandangkan kami tidak boleh menukar mekanisme satu utas JavaScript, bolehkah kami menggantung sementara beberapa tugas jangka panjang dan menunggu sehingga tugas utama selesai sebelum melaksanakan tugas yang dipasang ini? Pengarang JavaScript juga memikirkan cara ini JavaScript mempunyai tugas segerak dan tugas tak segerak.
Tugasan segerak bermaksud tugasan diletakkan dalam baris gilir pada urutan utama, dan tugasan seterusnya mesti menunggu selesainya tugasan sebelumnya sebelum ia boleh dilaksanakan. Tugasan tak segerak bermakna tugas itu tidak memasuki urutan utama, tetapi memasuki baris gilir tugasan untuk menunggu Tugas yang memasuki baris gilir tugas hanya akan masuk jika "baris gilir tugas" memberitahu urutan utama bahawa tugas tak segerak boleh dilaksanakan. Pelaksanaan utas utama.
Semua tugas penyegerakan JavaScript dilaksanakan pada urutan utama, membentuk tindanan pelaksanaan.
Baris gilir tugasan adalah berdasarkan prinsip masuk dahulu, keluar dahulu Acara dalam baris gilir lanjutan dilaksanakan dahulu dan acara dalam baris gilir input terakhir dilaksanakan kemudian.
Gelung Acara
Laksanakan tugas penyegerakan dalam tindanan pelaksanaan.
Apabila menghadapi tugasan tak segerak, ia tidak akan menunggu hasil pengembaliannya untuk sementara waktu dan terus melaksanakan tugasan segerak yang lain.
Apabila tugas tak segerak mendapat hasil, JavaScript akan menambah tugasan pada baris gilir tugas. Tugasan yang ditambahkan pada baris gilir tugasan tidak akan dilaksanakan serta-merta melalui panggilan balik, tetapi akan menunggu urutan utama (timbunan pelaksanaan) melahu sebelum ditambahkan pada tindanan pelaksanaan untuk pelaksanaan panggilan balik
Menunggu dalam timbunan pelaksanaan Tugas telah selesai.
Tambahkan tugasan dalam baris gilir tugasan pada tindanan pelaksanaan dan laksanakannya.
Ulangi ini untuk membentuk gelung tak terhingga. (Gambar di bawah adalah dari Internet)
Selepas mempelajari Event Loop, mari kita lihat soalan berikut:
setTimeout(function(){ console.log('setTimeout start') }); new Promise(function(resolve){ console.log('promise start'); resolve() }).then(function(){ console.log('promise then') }); console.log('script end');
Cuba ikuti apa yang kami katakan di atas Analisis mekanisme pelaksanaan JavaScript yang baru anda pelajari
1. Mula-mula laksanakan tugas segerak sehingga setTimeout, tetapi setTimeout ialah penggantungan sementara tugas tak segerak, menunggu pemasa tamat masa dan menambahnya ke baris gilir tugas.
2. Teruskan ke bawah dan laksanakan Janji Baharu yang baru mengandungi tugas penyegerakan dan mencetak "janji mula".
3. Tambah .kemudian pada baris gilir tugasan selepas melaksanakan azam.
4. Cetak "script end" selepas melaksanakan console.log('script end');
5. Pada masa ini, tugas utama telah dilaksanakan Tambahkan tugas tak segerak ke tugas utama dan laksanakannya secara langsung, cetak "setTimeout start", kemudian tambah .then pada tugas utama, dan cetak ". berjanji kemudian".
Jadi hasilnya sepatutnya: janji mula -> skrip tamat -> janji tamat masa?
Selepas melaksanakannya secara peribadi, hasilnya tidak seperti ini , tetapi janji bermula -> skrip tamat ->
Kemudian mengapa keputusan di atas tidak konsisten dengan apa yang kami jangkakan, dan mengapa setTimeout mula dicetak selepas janji.
Malah, ia adalah kerana pelaksanaan tak segerak juga berurutan. Sebenarnya, adalah tidak tepat untuk menggunakan kaedah tak segerak dan segerak untuk membahagikan susunan pelaksanaan baris gilir tugas. Ia harus dibahagikan kepada microtasks dan macrotasks.
Makro-tugas: kod skrip, setTimeout, setInterval
Mikro-tugas: Janji, proses seterusnya
Jadi setTimeout ialah tugas makro dalam tugas tak segerak, dan Promise ialah tugas mikro dalam tugas tak segerak. Sama ada ia adalah tugasan mikro atau tugasan makro, ia akan memasuki Barisan Acara yang sepadan Seterusnya kita melihat carta alir.
Mari kita fahami sedikit sebanyak:
1. Laksanakan tugasan makro (kod skrip)
2. Apabila microtask ditemui semasa melaksanakan macrotask, microtask akan ditambahkan pada Event Queue
3. Selepas macrotask semasa selesai, ia akan menjadi melihat Baris Gilir Peristiwa mikrotugas, dan laksanakan semua tugasan mikro dalam urutan
4. Selepas melaksanakan semua tugasan mikro, teruskan ke langkah pertama, dan kitaran ini
Ini juga merupakan mekanisme operasi javaScript Berdasarkan ini, mari kita analisa semula contoh di atas.
1. Mula-mula laksanakan tugas makro (kod skrip), dan apabila setTimeout ditemui, tambahkannya pada Baris Gilir Acara tugasan makro.
2. Teruskan melaksanakan Janji baharu dan cetak "janji mula".
3. Selepas melaksanakan untuk menyelesaikan, .kemudian adalah tugasan mikro, dan ditambahkan pada Barisan Acara bagi tugasan mikro.
4. Cetak "script end" selepas melaksanakan console.log('script end');
5. Pada ketika ini, semua tugasan makro pusingan ini telah dilaksanakan Pada masa ini, semak sama ada terdapat tugasan mikro boleh laksana dalam Barisan Eevent bagi tugasan mikro itu didapati terdapat tugasan mikro boleh laku sebentar tadi dalam Langkah ketiga 1: Tambah jumlah. kemudian, laksana dan cetak "janji kemudian"
6. Pada masa ini, pusingan pertama gelung acara telah tamat sepenuhnya, dan pusingan seterusnya gelung acara akan dilaksanakan tugas Makro pertama, mendapati setTimeout telah ditambahkan pada Baris Gilir Acara tugas makro, dilaksanakan dan dicetak "setTimeout start"
Sentiasa ingat bahawa JavaScript adalah satu utas, ia adalah, sedang, dan akan menjadi pada masa hadapan Ia akan menjadi. Semua bercakap tentang multi-threading adalah omong kosong.
Baris Gilir Acara bukan sahaja cara untuk melaksanakan tak segerak, tetapi juga mekanisme pelaksanaan js.
Boleh dilaksanakan menggunakan JavaScript pada masa hadapan. Semua akan dilaksanakan menggunakan JavaScript.
Cadangan berkaitan: Tutorial pembelajaran javascript
Atas ialah kandungan terperinci Kuasai sepenuhnya mekanisme pelaksanaan JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!