0Pricing
Frontend Academy · บทเรียน

Event Loop: Call Stack, Queue และ Microtasks

มองเห็นภาพการทำงานของ JavaScript ตั้งแต่ call stack คิวงาน และ microtasks จาก Promise รวมถึงเหตุผลที่ส่วนติดต่อผู้ใช้ไม่หยุดตอบสนองระหว่างการทำงานแบบอะซิงโครนัส

Event Loop: Call Stack, Queue และ Microtasks เป็นบทเรียน Frontend Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Frontend Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน

JavaScript เป็นแบบเธรดเดียว

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

สแตกการเรียก

สแตกการเรียกเป็นพื้นที่ที่ JavaScript ใช้ติดตามว่าฟังก์ชันใดกำลังทำงานอยู่ เมื่อมีการเรียกฟังก์ชัน ระบบจะใส่เฟรมเข้าไป เมื่อฟังก์ชันส่งคืนค่า ระบบจะนำเฟรมนั้นออก หากสแตกเต็มจากการเรียกซ้ำไม่รู้จบ จะเกิดสแตกโอเวอร์โฟลว์

function c() { /* does something */ }
function b() { c(); }
function a() { b(); }
a();

// Call stack during c():
// c    ← top
// b
// a
// (anonymous)

API บนเว็บ — ส่งต่องานออกไป

เมื่อ JavaScript เรียกใช้ฟังก์ชันแบบอะซิงโครนัส (setTimeout, fetch, addEventListener) งานจะถูกส่งต่อให้กับ API บนเว็บ ในเบราว์เซอร์ เอนจิน JS จะทำงานต่อที่บรรทัดถัดไป โดยไม่ต้องรอ

console.log('1');
setTimeout(() => console.log('2'), 0); // handed to Web API
console.log('3');
// Output: 1, 3, 2

คิวงาน (คิวแมโครทาสก์)

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

คิวไมโครทาสก์

พรอมิสใช้ คิวไมโครทาสก์ ซึ่งเป็นคิวที่มีลำดับความสำคัญสูง หลังจากงานแต่ละงานเสร็จสิ้นและก่อนเริ่มงานถัดไป ไมโครทาสก์ที่ค้างอยู่ทั้งหมดจะถูกประมวลผล ไมโครทาสก์จะทำงานก่อนแมโครทาสก์ถัดไปเสมอ

console.log('1');
setTimeout(() => console.log('timeout'), 0);  // macrotask
Promise.resolve().then(() => console.log('promise')); // microtask
console.log('2');
// Output: 1, 2, promise, timeout

ลูปเหตุการณ์ทำงานอย่างไร

อัลกอริทึมของลูปเหตุการณ์: 1) ดำเนินงานปัจจุบันจากสแตกการเรียกใช้จนกว่าสแตกจะว่าง 2) ประมวลผลไมโครทาสก์ทั้งหมดในคิว 3) แสดงผลหน้าจอเมื่อเหมาะสม 4) เลือกแมโครทาสก์ถัดไปแล้วทำซ้ำ

queueMicrotask()

queueMicrotask(fn) จะจัดกำหนดการให้ฟังก์ชันเรียกกลับทำงานในคิวไมโครทาสก์โดยไม่สร้างพรอมิส โดยทั่วไปไม่จำเป็นต้องเรียกใช้โดยตรง แต่มีประโยชน์ต่อการทำความเข้าใจว่าคลังโปรแกรมต่าง ๆ จัดกำหนดการทำงานอย่างไร

queueMicrotask(() => console.log('microtask'));
console.log('sync');
// Output: sync, microtask

เหตุใดงานที่ใช้เวลานานจึงทำให้ส่วนติดต่อผู้ใช้ค้าง

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

// Bad — blocks the UI for seconds:
for (let i = 0; i < 10_000_000; i++) { /* heavy work */ }

// Better — yield periodically:
async function processInChunks(items) {
  for (let i = 0; i < items.length; i++) {
    process(items[i]);
    if (i % 100 === 0) await new Promise(r => setTimeout(r, 0)); // yield
  }
}

เวิร์กเกอร์บนเว็บ — การทำงานแบบขนานอย่างแท้จริง

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

requestAnimationFrame

requestAnimationFrame(callback) จะจัดกำหนดการให้ฟังก์ชันเรียกกลับทำงานก่อนที่เบราว์เซอร์จะวาดหน้าจอใหม่ ใช้สำหรับภาพเคลื่อนไหวที่ควบคุมด้วย JavaScript เพราะจะทำงานสอดคล้องกับอัตราการรีเฟรชของจอแสดงผล ซึ่งโดยทั่วไปอยู่ที่ 60 เฟรมต่อวินาที

function animate(timestamp) {
  // update positions based on timestamp
  element.style.transform = `translateX(${timestamp * 0.1 % 400}px)`;
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

การเห็นภาพลูปเหตุการณ์

ตัวอย่างแบบโต้ตอบที่ latentflip.com/loupe ช่วยให้คุณวางโค้ดแล้วดูสแตกการเรียกใช้ API บนเว็บ คิวงาน และลูปเหตุการณ์ทำงานแบบช้าลงได้ เครื่องมือนี้จำเป็นอย่างยิ่งต่อการสร้างความเข้าใจเชิงสัญชาตญาณ

ตรวจสอบความเข้าใจ

หลังจากพรอมิสให้ผลสำเร็จ ฟังก์ชันเรียกกลับของ .then() จะทำงานในคิวใด

ทบทวน: ลูปเหตุการณ์

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

คำถามที่พบบ่อย

บทเรียน “Event Loop: Call Stack, Queue และ Microtasks” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “Event Loop: Call Stack, Queue และ Microtasks” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Frontend Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “Event Loop: Call Stack, Queue และ Microtasks”

มองเห็นภาพการทำงานของ JavaScript ตั้งแต่ call stack คิวงาน และ microtasks จาก Promise รวมถึงเหตุผลที่ส่วนติดต่อผู้ใช้ไม่หยุดตอบสนองระหว่างการทำงานแบบอะซิงโครนัส คุณปฏิบัติ Frontend Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Frontend Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Frontend Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “Event Loop: Call Stack, Queue และ Microtasks” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Frontend Academy นี้ได้ไหม

ได้ บทเรียน Frontend Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. Event Loop: Call Stack, Queue และ Microtasks
  2. Callback และ Callback Hell
  3. Promise: then, catch, finally และ Promise.all
  4. async/await และการจัดการข้อผิดพลาด
← กลับไปที่ Frontend Academy