ในบริบทของเอ็นจิ้นฝั่งเซิร์ฟเวอร์ Javascript สิ่งที่ไม่บล็อก I / O หรืออะซิงโครนัส I / O คืออะไร ฉันเห็นนี้ถูกกล่าวถึงว่าเป็นข้อได้เปรียบกว่าการใช้งานด้านเซิร์ฟเวอร์ Java
ในบริบทของเอ็นจิ้นฝั่งเซิร์ฟเวอร์ Javascript สิ่งที่ไม่บล็อก I / O หรืออะซิงโครนัส I / O คืออะไร ฉันเห็นนี้ถูกกล่าวถึงว่าเป็นข้อได้เปรียบกว่าการใช้งานด้านเซิร์ฟเวอร์ Java
คำตอบ:
การประมวลผลแบบซิงโครนัสมักจะหมายถึงการเรียกใช้โค้ดตามลำดับ การประมวลผลแบบอะซิงโครนัสหมายถึงการเรียกใช้ที่ไม่ได้ทำงานตามลำดับที่ปรากฏในรหัส ในตัวอย่างต่อไปนี้การดำเนินการแบบซิงโครนัสทำให้การแจ้งเตือนเริ่มทำงานตามลำดับ ในการดำเนินการ async ในขณะที่alert(2)
ดูเหมือนจะดำเนินการที่สองก็ไม่ได้
ซิงโครนัส: 1,2,3
alert(1);
alert(2);
alert(3);
แบบอะซิงโครนัส: 1,3,2
alert(1);
setTimeout(() => alert(2), 0);
alert(3);
การบล็อกหมายถึงการดำเนินการที่บล็อกการดำเนินการเพิ่มเติมจนกว่าการดำเนินการนั้นจะเสร็จสิ้น การไม่บล็อกหมายถึงโค้ดที่ไม่ได้บล็อกการทำงาน ในตัวอย่างที่กำหนดlocalStorage
คือการดำเนินการปิดกั้นตามที่จะหยุดการดำเนินการเพื่ออ่าน ในทางกลับกันfetch
เป็นการดำเนินการที่ไม่มีการปิดกั้นเนื่องจากไม่ได้ขัดขวางalert(3)
การทำงาน
// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);
// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);
ข้อดีอย่างหนึ่งของการดำเนินการแบบอะซิงโครนัสที่ไม่ปิดกั้นคือคุณสามารถเพิ่มการใช้งาน CPU สูงสุดเช่นเดียวกับหน่วยความจำ
ตัวอย่างของการดำเนินการแบบซิงโครนัสการบล็อกคือบางเว็บเซิร์ฟเวอร์เช่นใน Java หรือ PHP จัดการ IO หรือคำขอเครือข่าย หากรหัสของคุณอ่านจากไฟล์หรือฐานข้อมูลรหัสของคุณ "บล็อก" ทุกอย่างหลังจากที่เรียกใช้งาน ในช่วงเวลาที่เครื่องของคุณถือเข้าสู่หน่วยความจำและการประมวลผลเวลาสำหรับหัวข้อที่ไม่ได้ทำอะไร
เพื่อตอบสนองคำขออื่น ๆ ในขณะที่เธรดนั้นค้างอยู่นั้นขึ้นอยู่กับซอฟต์แวร์ของคุณ สิ่งที่ซอฟต์แวร์เซิร์ฟเวอร์ส่วนใหญ่ทำคือวางไข่เธรดเพิ่มเติมเพื่อรองรับคำขอเพิ่มเติม สิ่งนี้ต้องการหน่วยความจำที่ใช้มากขึ้นและการประมวลผลที่มากขึ้น
เซิร์ฟเวอร์แบบอะซิงโครนัสและไม่มีการปิดกั้น - เช่นเดียวกับที่ทำในโหนดใช้เพียงเธรดเดียวเพื่อให้บริการคำขอทั้งหมด นี่หมายถึงอินสแตนซ์ของโหนดทำให้เกิดประโยชน์สูงสุดจากเธรดเดียว ผู้สร้างออกแบบมาพร้อมหลักฐานว่าการดำเนินการ I / O และเครือข่ายเป็นคอขวด
เมื่อคำขอมาถึงที่เซิร์ฟเวอร์พวกเขาจะได้รับบริการทีละครั้ง อย่างไรก็ตามเมื่อโค้ดเซอร์วิสต้องการเคียวรี DB จะส่งการเรียกกลับไปยังคิวที่สองและเธรดหลักจะทำงานต่อไป (ไม่ต้องรอ) ตอนนี้เมื่อการดำเนินการฐานข้อมูลเสร็จสมบูรณ์และส่งกลับการเรียกกลับที่สอดคล้องกันดึงออกจากคิวที่สองและเข้าคิวในคิวที่สามที่พวกเขากำลังรอการดำเนินการ เมื่อเอ็นจิ้นได้รับโอกาสที่จะดำเนินการอย่างอื่น (เช่นเมื่อสแต็คการดำเนินการถูกทำให้ว่างเปล่า) มันจะทำการเรียกกลับจากคิวที่สามและดำเนินการ
var startTime = new Date().getTime();
var getEndTime = () => {
var tempEndTime = new Date().getTime();
var second = (tempEndTime - startTime)/1000
return `took ${second} sec...to finish\n`
}
console.log('1: start App', getEndTime())
setTimeout(()=>{
console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())
// console -> Process Order: 1 -> 3 -> 2