Skip to content
fearchitect
Browser & Runtime Internals

Event Loop & scheduler.yield()

Break long tasks to keep the main thread responsive and hit INP.

By Abas TurabliReviewed

Summary

The browser event loop processes one task at a time on the main thread. Any task exceeding 50 ms blocks input handling and worsens INP. `scheduler.yield()` lets long work pause mid-loop so the browser can handle a pending click before resuming — with a prioritized continuation that avoids the starvation risk of `setTimeout(0)`.

Jump to the interview angle
Each event-loop iteration: one macrotask, then all microtasks, then a render frame if the browser decides one is due.

How a long task hurts INP

  1. 1

    User clicks a button

    The browser queues a click event as a macrotask. It cannot dispatch it until the currently running task finishes.

  2. 2

    A long task blocks the thread

    Your event handler or a third-party script runs for 300 ms. No other tasks execute; the click sits in the queue.

  3. 3

    Input delay accumulates

    The browser finally processes the click only after the long task completes. That 300 ms gap counts directly toward INP.

  4. 4

    Yield and resume

    Inserting await scheduler.yield() mid-task ends the current task, lets the browser dispatch the click, then resumes your work in a new prioritized task.

Breaking a long loop with scheduler.yield()

Process items in batches and yield every 50 ms. The continuation runs at user-visible priority so it resumes before background tasks but after any pending input events.

Batch-process with scheduler.yield()ts
async function processItems(items: string[]): Promise<void> {
  // Feature-detect; fall back to setTimeout for Safari.
  const yieldFn: () => Promise<void> =
    typeof scheduler !== "undefined" && scheduler.yield
      ? () => scheduler.yield()
      : () => new Promise<void>((resolve) => setTimeout(resolve, 0));

  let deadline = performance.now() + 50;

  for (const item of items) {
    doWork(item);

    if (performance.now() >= deadline) {
      await yieldFn();          // pause; browser handles input here
      deadline = performance.now() + 50;
    }
  }
}

Yield every 50 ms so no single task exceeds the long-task threshold. Safari falls back to setTimeout(0) — no priority guarantee, but still yields.

Yield mechanisms compared

APIPrioritySupportContinuation guarantee
scheduler.yield()user-visible (inherits postTask priority)Chromium + Firefox; not SafariResumes before background tasks
setTimeout(0)No priority — joins back of task queueAll browsersNo; any queued task may run first
scheduler.postTask()user-blocking / user-visible / backgroundChromium + Firefox; not SafariYes, per declared priority
MessageChannelRoughly macro-task level, no priorityAll browsersNo; similar to setTimeout(0)

Avoid isInputPending()

navigator.scheduling.isInputPending() was an early yield-heuristic. web.dev now recommends against it: it can return false during real input and does not account for animation frames. Use scheduler.yield() with a time-based deadline instead.

Interview angle

Interviewers probe whether you know why long tasks hurt INP and how to break them without losing work. Describe the task → microtask → render cycle, then explain why scheduler.yield() beats setTimeout(0) for continuations.

Soundbite: "scheduler.yield() pauses a task and re-queues its continuation at user-visible priority, so the browser handles input before resuming your work."

Key terms

macrotask
A single unit of work the event loop picks from the task queue: a script, event callback, or timer.
microtask
Work queued via Promise resolution or `queueMicrotask`; drains entirely after each task before rendering.
long task
Any main-thread task exceeding 50 ms; blocks input handling and increases INP.
INP
Interaction to Next Paint — 98th-percentile input-to-paint delay; good ≤200 ms.
scheduler.yield()
Prioritized Task Scheduling API method that pauses a task and re-queues its continuation at user-visible priority.

Further reading

Search fearchitect

Jump to a topic, mode, or action.