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

งานไมโครและพรอมิส

เรียนรู้ว่าเหตุใดการเรียกกลับของพรอมิสจึงทำงานก่อน

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

ไมโครทาสก์คืออะไร

ไมโครทาสก์ คืองานที่เลื่อนไว้ซึ่งมีลำดับความสำคัญสูง ฟังก์ชันเรียกกลับของพรอมิส (.then, .catch, .finally) และ queueMicrotask ต่างก็จัดตารางไมโครทาสก์

กฎสำคัญคือ หลังการทำงานแบบซิงโครนัสแต่ละครั้ง ระบบจะประมวลผลไมโครทาสก์ ทั้งหมดจนหมดก่อนแมโครทาสก์ใด ๆ

ฟังก์ชันเรียกกลับของพรอมิสทำงานภายหลัง

แม้พรอมิสที่ resolve แล้วก็ยังจัดตารางฟังก์ชันเรียกกลับ .then เป็นไมโครทาสก์ ฟังก์ชันนี้จะไม่ทำงานแบบซิงโครนัส

console.log('start');
Promise.resolve().then(() => console.log('promise then'));
console.log('end');

ไมโครทาสก์มาก่อนแมโครทาสก์

นี่คือกฎการเรียงลำดับที่สำคัญที่สุด ฟังก์ชันเรียกกลับของพรอมิสจะทำงาน ก่อนฟังก์ชันเรียกกลับของ setTimeout แม้ว่าจะจัดตารางตัวจับเวลาไว้ก่อนก็ตาม

setTimeout(() => console.log('timeout (macro)'), 0);
Promise.resolve().then(() => console.log('promise (micro)'));
console.log('sync');

คิวไมโครทาสก์จะถูกประมวลผลจนหมด

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

setTimeout(() => console.log('macro'), 0);
Promise.resolve().then(() => console.log('micro 1'));
Promise.resolve().then(() => console.log('micro 2'));
console.log('sync');

พรอมิสที่เชื่อมต่อกัน

.then แต่ละรายการในสายจะจัดตารางไมโครทาสก์ใหม่เมื่อรายการก่อนหน้าเสร็จสิ้น ไมโครทาสก์เหล่านี้จะยังคงทำงานก่อนตัวจับเวลาที่รออยู่เสมอ

setTimeout(() => console.log('timeout'), 0);
Promise.resolve()
  .then(() => console.log('then 1'))
  .then(() => console.log('then 2'))
  .then(() => console.log('then 3'));
console.log('sync');

ไมโครทาสก์ที่จัดตารางระหว่างการประมวลผลคิว

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

Promise.resolve().then(() => {
  console.log('micro A');
  Promise.resolve().then(() => console.log('micro B (added later)'));
});
setTimeout(() => console.log('macro'), 0);
console.log('sync');

ค่าที่ resolve แล้วส่งต่อไปตามสาย

ค่าที่ส่งคืนจากตัวจัดการ .then จะกลายเป็นข้อมูลนำเข้าของตัวจัดการถัดไปในสาย โดยทั้งหมดทำงานผ่านไมโครทาสก์

Promise.resolve(2)
  .then(n => n * 3)
  .then(n => n + 1)
  .then(n => console.log('result', n));
console.log('sync first');

อะซิงก์/อะเวตใช้ไมโครทาสก์

โค้ดหลังคำสั่ง await จะทำงานต่อในรูปแบบไมโครทาสก์ ดังนั้นการทำงานต่อหลังการรอจึงเกิดขึ้นก่อนตัวจับเวลาที่จัดตารางไว้ก่อนหน้า

async function run() {
  console.log('a');
  await null;
  console.log('c (after await)');
}
setTimeout(() => console.log('d (timeout)'), 0);
run();
console.log('b');

ตัวอย่างการเรียงลำดับแบบรวม

ลองนำทุกอย่างมารวมกัน แล้วทำนายลำดับการทำงาน: โค้ดซิงโครนัสก่อน จากนั้นไมโครทาสก์ทั้งหมด แล้วจึงเป็นแมโครทาสก์

console.log('1 sync');
setTimeout(() => console.log('5 timeout'), 0);
Promise.resolve().then(() => console.log('3 promise'));
Promise.resolve().then(() => console.log('4 promise'));
console.log('2 sync');

เหตุใดไมโครทาสก์ที่ทำให้งานอื่นอดทำงานจึงมีความเสี่ยง

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

let n = 0;
function loop() {
  if (n++ < 3) {
    console.log('micro ' + n);
    Promise.resolve().then(loop);
  }
}
setTimeout(() => console.log('macro after micros'), 0);
loop();

เหตุใดลำดับนี้จึงสำคัญ

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

console.log('A');
Promise.resolve().then(() => console.log('B'));
setTimeout(() => console.log('D'), 0);
console.log('C');

ตรวจสอบความเข้าใจอย่างรวดเร็ว

พรอมิส .then และ setTimeout(fn, 0) ต่างก็อยู่ระหว่างรอ รายการใดจะทำงานก่อน

ทบทวน: ไมโครทาสก์และพรอมิส

คุณได้เรียนรู้กฎด้านลำดับความสำคัญดังนี้

  • ไมโครทาสก์ มาจากพรอมิสและ queueMicrotask
  • ไมโครทาสก์ทั้งคิวจะถูก ประมวลผลจนหมดก่อนแมโครทาสก์ใด ๆ
  • การทำงานต่อของ async/await เป็นไมโครทาสก์
  • สายไมโครทาสก์ที่ไม่สิ้นสุดอาจขัดขวางตัวจับเวลาและการแสดงผล

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

บทเรียน “งานไมโครและพรอมิส” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “งานไมโครและพรอมิส”

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

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

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

บทเรียน “งานไมโครและพรอมิส” ใช้เวลานานแค่ไหน

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

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

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

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

  1. สแต็กการเรียก
  2. งานแมโครและคิวงาน
  3. งานไมโครและพรอมิส
  4. queueMicrotask และลำดับการทำงาน
← กลับไปที่ JavaScript Academy