JavaScript จัดการกับการตอบสนอง AJAX ในพื้นหลังได้อย่างไร


139

เนื่องจาก JavaScript ทำงานในเธรดเดียวหลังจากที่ร้องขอ AJAX แล้วจะเกิดอะไรขึ้นในพื้นหลัง ฉันต้องการทราบข้อมูลเชิงลึกเกี่ยวกับเรื่องนี้มากขึ้น


6
คำอธิบายที่ดีงามอยู่ที่นี่: stackoverflow.com/questions/2914161/ajax-multi-threaded
Jonathan M

3
รหัส JavaScript เป็นเธรดเดี่ยว (ยกเว้นสำหรับผู้ทำงานทางเว็บ) แต่ไม่ใช่เบราว์เซอร์ที่ใช้งานเครื่องมือ JavaScript ...
Juan Mendes

@JuanMendes JavaScript ทำงานในหนึ่งเธรดในขณะที่ Event Queue ทำงานในเธรดอื่นหรือไม่
Shaun Luttin

1
@ShaunLuttin ไม่คิวกิจกรรมคือสิ่งที่เริ่มต้นด้วย JavaScript
Juan Mendes

คำตอบ:


213

ด้านล่างหน้าปกจาวาสคริปต์มีคิวเหตุการณ์ แต่ละครั้งที่การประมวลผลเธรด javascript เสร็จสิ้นจะตรวจสอบว่ามีเหตุการณ์อื่นในคิวที่จะดำเนินการหรือไม่ หากมีมันจะดึงออกจากคิวและทริกเกอร์เหตุการณ์นั้น (เช่นการคลิกเมาส์เป็นต้น)

เครือข่ายโค้ดเนทีฟที่อยู่ภายใต้การโทร ajax จะรู้ได้เมื่อการตอบกลับ ajax เสร็จสิ้นและเหตุการณ์จะถูกเพิ่มเข้าในคิวเหตุการณ์ของจาวาสคริปต์ โค้ดเนทีฟรู้ได้อย่างไรเมื่อทำการโทร ajax ขึ้นอยู่กับการนำไปใช้งาน อาจถูกนำไปใช้กับเธรดหรืออาจเป็นตัวขับเคลื่อนเหตุการณ์เอง (มันไม่สำคัญ) จุดประสงค์ของการนำไปใช้คือเมื่อการตอบสนอง ajax เสร็จสิ้นโค้ดเนทีฟบางตัวจะรู้ว่าเสร็จสิ้นแล้วและใส่เหตุการณ์ลงในคิว JS

หากไม่มี Javascript ทำงานในเวลากิจกรรมจะถูกเรียกใช้ทันทีซึ่งจะเรียกใช้ตัวจัดการการตอบกลับ ajax หากมีบางอย่างกำลังทำงานอยู่เหตุการณ์จะถูกประมวลผลเมื่อเธรด javascript ปัจจุบันของการดำเนินการเสร็จสิ้น ไม่จำเป็นต้องมีการลงคะแนนใด ๆ โดยเครื่องมือจาวาสคริปต์ เมื่อ Javascript ชิ้นหนึ่งทำงานเสร็จแล้วเอ็นจิ้น JS จะตรวจสอบคิวเหตุการณ์เพื่อดูว่ามีสิ่งใดที่ต้องใช้อีกหรือไม่ ถ้าเป็นเช่นนั้นมันจะป็อปอัพเหตุการณ์ถัดไปที่ปิดคิวและเรียกใช้งานมัน (การเรียกฟังก์ชันการเรียกกลับอย่างน้อยหนึ่งฟังก์ชันที่ลงทะเบียนไว้สำหรับเหตุการณ์นั้น) หากไม่มีอะไรอยู่ในคิวเหตุการณ์แล้วล่าม JS มีเวลาว่าง (การรวบรวมขยะหรือไม่ได้ใช้งาน) จนกว่าเอเจนต์ภายนอกบางอย่างจะใส่อย่างอื่นในคิวเหตุการณ์และปลุกอีกครั้ง

เนื่องจากกิจกรรมภายนอกทั้งหมดผ่านคิวกิจกรรมและไม่มีเหตุการณ์ใดถูกเรียกใช้ในขณะที่จาวาสคริปต์ใช้งานอย่างอื่นอยู่จึงยังคงมีเธรดเดียว

นี่คือบทความบางส่วนเกี่ยวกับรายละเอียด:


ขอบคุณสำหรับสิ่งนั้น ฉันสงสัยว่านี่เป็นกรณี แต่ก็ดีที่จะรู้แน่นอน ฉันมีการวนรอบซึ่งฉันส่งคำขอ 'ajax' จำนวนมาก ในตัวจัดการของฉัน (สำหรับแต่ละคำขอ - ส่งคืนตามลำดับโดยพลการ) ฉันเรียกใช้โค้ดบางอย่างที่อาจใช้เวลาพอสมควร เป็นการดีที่จะรู้ว่าสิ่งนี้ควรจะได้ผลแน่นอน
iPadDeveloper2011

4
@telandor - เหตุการณ์ถูกเรียกใช้ตามลำดับ FIFO (เป็นไปได้ว่ามีข้อยกเว้นบางกรณี แต่เจตนาคือ FIFO) เหตุการณ์บางอย่างจะถือว่าแตกต่างกันเล็กน้อย ตัวอย่างเช่นเหตุการณ์ mousemove จะไม่เกิดขึ้นในคิว (อาจเป็นเพราะพวกเขาสามารถล้นคิวได้ง่าย) เมื่อเมาส์เคลื่อนย้ายและเหตุการณ์ mousemove อยู่ในคิวแล้วและไม่มีเหตุการณ์ที่ใหม่กว่าในคิวมันจะถูกอัปเดตด้วยตำแหน่งล่าสุดแทนที่จะเพิ่มกิจกรรมใหม่ ฉันเดาว่าเหตุการณ์จับเวลาช่วงอาจได้รับการปฏิบัติเป็นพิเศษเพื่อหลีกเลี่ยงการซ้อนในคิว
jfriend00

2
@telandor - คุณต้องการคำอธิบายอะไรเพิ่มเติมอีกบ้าง? มันคือ FIFO ฉันเพิ่มบทความอ้างอิงอีกสองสามข้อในคำตอบของฉัน การประหารชีวิตเพียงครั้งเดียวกับ FIFO ที่ฉันรู้ว่าเป็นเหตุการณ์ที่เกิดขึ้นทันที คุณโทร.focus()หารายการและเรียกใช้เหตุการณ์อื่นสองสามรายการเช่นเหตุการณ์ "เบลอ" ในรายการที่มีโฟกัส เหตุการณ์ความพร่ามัวเกิดขึ้นพร้อมกันและไม่ผ่านคิวเหตุการณ์ดังนั้นมันจะเกิดขึ้นทันทีก่อนสิ่งอื่น ๆ ที่อาจอยู่ในคิวเหตุการณ์ ในทางปฏิบัติฉันไม่เคยพบว่าสิ่งนี้เป็นข้อกังวลในทางปฏิบัติ
jfriend00

2
@telandor - ไม่มีคิวหลายต่อเอกสารเบราว์เซอร์ มีหนึ่งคิวและทุกอย่างเป็นไปตามลำดับ FIFO เข้า / ออก ดังนั้นการหมดเวลาและการตอบกลับ ajax และเหตุการณ์เมาส์และเหตุการณ์แป้นพิมพ์ทั้งหมดจึงอยู่ในคิวเดียวกัน สิ่งใดก็ตามที่ถูกใส่ในคิวก่อนที่จะถูกเรียกใช้ก่อน
jfriend00

1
@CleanCrispCode - ขอบคุณ ฉันเพิ่มมันเป็นข้อมูลอ้างอิงที่มีประโยชน์กับคำตอบของฉัน
jfriend00

16

คุณสามารถค้นหาที่นี่เอกสารที่สมบูรณ์มากเกี่ยวกับเหตุการณ์การจัดการใน JavaScript
มันเขียนโดยคนที่ทำงานเกี่ยวกับการใช้งานจาวาสคริปต์ในเบราว์เซอร์ Opera

ดูรายละเอียดเพิ่มเติมได้ที่: "การไหลของเหตุการณ์", "การจัดกิจกรรม" และ "กิจกรรมที่ไม่ใช่ผู้ใช้": คุณจะได้เรียนรู้ว่า:

  1. Javascript ทำงานในเธรดเดียวสำหรับแต่ละแท็บเบราว์เซอร์หรือหน้าต่าง
  2. เหตุการณ์ถูกจัดคิวและดำเนินการตามลำดับ
  3. XMLHttpRequest ถูกเรียกใช้โดยการนำไปใช้และการเรียกกลับจะถูกเรียกใช้โดยใช้คิวเหตุการณ์

หมายเหตุ: ลิงค์เดิมคือ: ลิงค์แต่ตอนนี้ตายไปแล้ว


1

ฉันต้องการอธิบายรายละเอียดเล็กน้อยเกี่ยวกับ ajax Implementation ที่กล่าวถึงในคำตอบ

แม้ว่า (ปกติ) การทำงานของ JavaScript คือไม่ได้แบบมัลติเธรด - ตามที่ระบุไว้ในคำตอบที่ดีดังกล่าวข้างต้น - อย่างไรก็ตาม , การจัดการที่แท้จริงของAJAX responses(เช่นเดียวกับการจัดการการร้องขอ) เป็นไม่ Javascript และมัน - ปกติ - เป็นแบบมัลติเธรด (ดูการใช้งานแหล่งโครเมียมของ XMLHttpRequest ซึ่งเราจะให้จานด้านบน)

และฉันจะอธิบายให้ใช้รหัสต่อไปนี้:

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(- หลังจากขั้นตอนที่ 1) จากนั้นในขณะที่รหัส js ของคุณดำเนินการ (ขั้นตอนที่ 2 และหลัง) เบราว์เซอร์เริ่มทำงานจริง: 1. การจัดรูปแบบคำขอ tcp 2. เปิดซ็อกเก็ต 3. ส่งส่วนหัว 4. การจับมือกัน 5. การส่ง เนื้อความ 6. การรอการตอบกลับ 7. การอ่านส่วนหัว 8. การอ่านเนื้อหา ฯลฯ การใช้งานทั้งหมดนี้มักจะรันอยู่ในเธรดที่ต่างกันควบคู่ไปกับการเรียกใช้โค้ด js ของคุณ ตัวอย่างเช่นการใช้งานโครเมียมที่กล่าวถึงนั้นใช้Threadable Loader go digg-in 😉, (คุณสามารถรับความประทับใจได้ด้วยการดูที่แท็บเครือข่ายของการโหลดหน้าเว็บคุณจะเห็นคำขอบางอย่างพร้อมกัน)

โดยสรุปฉันจะบอกว่า - อย่างน้อย - การดำเนินการ I / O ส่วนใหญ่ของคุณสามารถทำได้พร้อมกัน / async (และคุณสามารถใช้ประโยชน์จากสิ่งนี้ได้โดยใช้การรอตัวอย่าง) แต่การโต้ตอบทั้งหมดกับการดำเนินการเหล่านั้น (การดำเนินการการเรียกกลับ js) ล้วนเป็นแบบซิงโครนัส

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.