Bagaimana JavaScript menangani respons AJAX di latar belakang?

139

Karena JavaScript berjalan dalam satu utas, setelah permintaan AJAX dibuat, apa yang sebenarnya terjadi di latar belakang? Saya ingin mendapatkan wawasan yang lebih dalam tentang hal ini, adakah yang bisa menjelaskan?

aziz punjani
sumber
6
Deskripsi yang cukup bagus ada di sini: stackoverflow.com/questions/2914161/ajax-multi-threaded
Jonathan M
3
Kode JavaScript adalah utas tunggal (kecuali untuk pekerja web), tetapi bukan browser yang menjalankan mesin JavaScript ...
Juan Mendes
@JuanMendes Apakah JavaScript berjalan di satu utas sementara Antrian Acara berjalan di utas lainnya?
Shaun Luttin
1
@ShaunLuttin Tidak, antrian acara adalah yang mengawali JavaScript
Juan Mendes

Jawaban:

213

Di bawah selimut, javascript memiliki antrian acara. Setiap kali thread javascript eksekusi selesai, ia memeriksa untuk melihat apakah ada acara lain dalam antrian untuk diproses. Jika ada, itu menariknya keluar dari antrian dan memicu acara itu (seperti klik mouse, misalnya).

Jaringan kode asli yang terletak di bawah panggilan ajax akan tahu kapan respons ajax dilakukan dan suatu peristiwa akan ditambahkan ke antrian acara javascript. Bagaimana kode asli mengetahui kapan panggilan ajax dilakukan tergantung pada implementasinya. Ini dapat diimplementasikan dengan utas atau mungkin juga didorong oleh peristiwa itu sendiri (itu tidak masalah). Inti dari implementasi adalah bahwa ketika respon ajax dilakukan, beberapa kode asli akan tahu itu dilakukan dan memasukkan suatu peristiwa ke dalam antrian JS.

Jika tidak ada Javascript yang berjalan pada saat itu, acara akan segera dipicu yang akan menjalankan penangan respons ajax. Jika sesuatu berjalan pada saat itu, maka acara tersebut akan diproses ketika utas eksekusi javascript saat ini selesai. Tidak perlu ada polling oleh mesin javascript. Ketika sepotong Javascript selesai dieksekusi, mesin JS hanya memeriksa antrian acara untuk melihat apakah ada hal lain yang perlu dijalankan. Jika demikian, ini akan memunculkan acara berikutnya dari antrian dan mengeksekusinya (memanggil satu atau lebih fungsi panggilan balik yang terdaftar untuk acara itu). Jika tidak ada dalam antrian acara, maka penerjemah JS memiliki waktu luang (pengumpulan sampah atau menganggur) sampai beberapa agen eksternal memasukkan sesuatu yang lain dalam antrian acara dan membangunkannya lagi.

Karena semua peristiwa luar melewati antrian acara dan tidak ada peristiwa yang dipicu saat javascript menjalankan sesuatu yang lain, ia tetap berurutan tunggal.

Berikut beberapa artikel tentang perinciannya:

pacar00
sumber
Terima kasih untuk itu. Saya curiga inilah masalahnya, tetapi baik untuk mengetahui dengan pasti. Saya memiliki for for loop, di mana saya mengirimkan banyak permintaan 'ajax'. Dalam handler saya (untuk setiap permintaan - dikembalikan dalam urutan acak) saya menjalankan beberapa kode yang mungkin memakan waktu. Senang mengetahui ini pasti harus bekerja.
iPadDeveloper2011
4
@telandor - acara dijalankan dalam urutan FIFO (mungkin ada beberapa pengecualian kasus tepi, tetapi tujuannya adalah FIFO). Beberapa peristiwa diperlakukan sedikit berbeda. Misalnya acara mousemove tidak menumpuk di antrian (mungkin karena mereka dapat dengan mudah meluap antrian). Ketika mouse bergerak dan acara mouse harus dalam antrian dan tidak ada acara baru lainnya dalam antrian, itu diperbarui dengan posisi terbaru daripada acara baru ditambahkan. Saya akan menebak bahwa peristiwa interval waktu mungkin juga diperlakukan secara khusus untuk menghindari mereka menumpuk di antrian.
jfriend00
2
@telandor - apa yang perlu Anda jelaskan lebih lanjut? Itu FIFO. Saya menambahkan beberapa artikel referensi ke jawaban saya. Satu-satunya eksekusi ke FIFO yang saya ketahui segera memicu peristiwa. Anda memanggil .focus()item dan yang memicu beberapa peristiwa lain seperti acara "blur" pada item dengan fokus. Kejadian kabur itu terjadi secara serempak dan tidak melalui antrian acara sehingga akan terjadi segera sebelum hal-hal lain yang mungkin ada dalam antrian acara. Dalam praktiknya, saya tidak pernah menemukan ini sebagai masalah praktis.
jfriend00
2
@telandor - Tidak ada banyak antrian per dokumen peramban. Ada satu antrian dan semuanya berjalan FIFO secara serial masuk / keluar. Jadi respons timeout dan ajax dan acara mouse dan acara keyboard semuanya berjalan dalam antrian yang sama. Mana pun yang dimasukkan ke dalam antrian, pertama-tama dijalankan terlebih dahulu.
jfriend00
1
@CleanCrispCode - Thx. Saya menambahkannya sebagai referensi yang bermanfaat untuk jawaban saya.
jfriend00
16

Anda dapat menemukan di sini dokumentasi yang sangat lengkap tentang penanganan peristiwa dalam javascript.
Ini ditulis oleh seorang pria yang bekerja pada implementasi javascript di Opera Browser.

Lebih tepatnya, lihat judul: "Alur Acara", "Antrian Acara" dan "Acara Non-pengguna": Anda akan belajar bahwa:

  1. Javascript berjalan dalam satu utas untuk setiap tab atau jendela browser.
  2. Acara diantrekan dan dieksekusi secara berurutan.
  3. XMLHttpRequest dijalankan oleh implementasi dan callback dijalankan menggunakan antrian acara.

Catatan: Tautan asli tadinya: tautan , tetapi sekarang mati.

qwertzguy
sumber
1

Saya ingin menguraikan sedikit, mengenai Implementasi ajax yang disebutkan dalam jawaban.

Meskipun (biasa) eksekusi Javascript tidak multi-threaded - seperti yang tercantum baik dalam jawaban di atas - Namun , penanganan nyata dari AJAX responses(serta penanganan permintaan) adalah tidak Javascript, dan - biasanya - adalah multi-threaded. (lihat implementasi sumber kromium dari XMLHttpRequest yang akan kita diskusikan di atas)

dan saya akan jelaskan, mari kita ambil kode berikut:

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
		console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made(- setelah langkah 1), kemudian saat kode js Anda mulai mengeksekusi (langkah 2 dan setelah), browser memulai pekerjaan nyata: 1. memformat permintaan tcp 2. membuka soket 3. mengirim header 3. mengirim header 4. berjabat tangan 5. mengirim 5. tubuh 6. respons menunggu 7. membaca header 8. membaca tubuh dll. semua implementasi ini biasanya berjalan di utas yang berbeda secara paralel dengan eksekusi kode js Anda. sebagai contoh, implementasi kromium yang disebutkan menggunakan Threadable Loader masuk digg-ke 😉, (Anda juga bisa mendapatkan kesan dengan melihat tab jaringan dari pemuatan halaman, Anda akan melihat beberapa permintaan simultan).

sebagai kesimpulan, saya akan mengatakan bahwa - setidaknya - sebagian besar operasi I / O Anda dapat dilakukan secara bersamaan / async (dan Anda dapat mengambil keuntungan dari ini menggunakan menunggu misalnya). tetapi semua interaksi dengan operasi-operasi tersebut (yang mengeluarkan, eksekusi js callback) semuanya sinkron.

tukang goreng shmulik
sumber