Lange taken opsplitsen

Webfuncties: Scheduler API

Zware berekeningen of lange lussen kunnen de primaire thread blokkeren, waardoor de pagina niet meer reageert. Je kunt dit voorkomen door de controle regelmatig terug te geven aan de browser. Met de scheduler.yield() API kun je een lange taak onderbreken en de browser gebruikersinvoer of weergave laten verwerken voordat je doorgaat.

Lange taken opsplitsen

Gebruik scheduler.yield() in asynchrone functies om werk op te splitsen.

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;
    }
  }
}

Reservestrategieën

Sommige browsers ondersteunen de scheduler API misschien niet. Je MOET een fallback implementeren met setTimeout om te zorgen dat de code wordt uitgevoerd zonder fouten.

Reserve voor 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;
    }
  }
}