แบ่งงานที่ใช้เวลานานออกเป็นส่วนๆ

ฟีเจอร์บนเว็บ: Scheduler API

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

การแบ่งงานที่ใช้เวลานาน

ใช้ scheduler.yield() ภายในฟังก์ชันแบบไม่พร้อมกันเพื่อแบ่งงาน

async function processLargeArray(items) {
  // DO: Set a time-based deadline 50 milliseconds into the future. 50
  // milliseconds is the boundary for when a task becomes a long task.
  let deadline = performance.now() + 50; // 50ms budget

  for (const item of items) {
    // Process the item
    processItem(item);
    
    // MANDATORY: Yield to the main thread periodically to keep the UI
    // responsive. This can be done by checking if the deadline set earlier
    // has been exceeded. When it has been, yield, then reset the deadline
    // another 50 milliseconds into the future.
    if (performance.now() >= deadline) {
      await scheduler.yield();
      deadline = performance.now() + 50;
    }
  }
}

กลยุทธ์สำรอง

เบราว์เซอร์บางรายการอาจไม่รองรับ scheduler API คุณต้องใช้โหมดสำรองโดยใช้ setTimeout เพื่อให้โค้ดทำงานได้โดยไม่ขัดข้อง

สำรองสำหรับ scheduler.yield()

async function processLargeArrayWithFallback(items) {
  // DO: Set a time-based deadline 50 milliseconds into the future.
  let deadline = performance.now() + 50;

  for (const item of items) {
    processItem(item);
    
    // MANDATORY: Yield to the main thread periodically to keep the UI responsive.
    if (performance.now() >= deadline) {
      // DO: Feature detect scheduler.yield
      if ('scheduler' in window && 'yield' in window.scheduler) {
        await scheduler.yield();
      } else {
        // DO: Fallback to setTimeout for older browsers
        await new Promise(resolve => setTimeout(resolve, 0));
      }
      deadline = performance.now() + 50;
    }
  }
}